触发和停止时间手动在Golang中的股票行情通道

So I have this code, it accepts user entry of one, two, or three. It prints Ticker ticked depending on the duration selected. I need help on how to stop the ticker first before activating the ticker again with a different duration.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    for {
        fmt.Print("> ")

        text, _ := reader.ReadString('
')
        text = strings.Replace(text, "
", "", -1)

        switch text {
        case "one":
            go timeTick(true, 1)
        case "two":
            go timeTick(true, 2)
        case "three":
            go timeTick(true, 3)
        default:
            go timeTick(false, 0)
        }
    }
}

func timeTick(flag bool, tick int) {
    var tickChan *time.Ticker

    if flag {
        tickChan = time.NewTicker(time.Second * time.Duration(tick))
    }

    doneChan := make(chan bool)

    if !flag {
        doneChan <- true
    }

    for {
        select {
        case <-tickChan.C:
            fmt.Println("Ticker ticked")
        case <-doneChan:
            fmt.Println("Done")
            return
        }
    }
}

So user inputs either, one, two, or three to activate the ticker else it will send true to doneChan channel.

When I activated the ticker with one. It prints Ticker ticked every second but how do I stop the ticker when I input two or three while the ticker is running? It then brings me to my main question, why is doneChan not triggered at all even inputting a random string?

You need to pass in the channel used to signal completion. You always want to cancel the current ticker if there is one, so you can attempt a send in each iteration of the main for loop. Since the channel isn't buffered, a send operation is blocking, so you need to attempt the send in a select statement with a default case to prevent a deadlock in the case you don't have a current ticker attempting to read from the channel.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    tickerDone := make(chan struct{})

    for {
        fmt.Print("> ")

        text, _ := reader.ReadString('
')
        text = strings.Replace(text, "
", "", -1)

        select {
        case tickerDone <- struct{}{}:
        default:
        }

        switch text {
        case "one":
            go timeTick(1, tickerDone)
        case "two":
            go timeTick(2, tickerDone)
        case "three":
            go timeTick(3, tickerDone)
        }
    }
}

func timeTick(tick int, done <-chan struct{}) {
    tickChan := time.NewTicker(time.Second * time.Duration(tick))

    for {
        select {
        case <-tickChan.C:
            fmt.Println("Ticker ticked")
        case <-done:
            fmt.Println("Done")
            return
        }
    }
}

You can try this code below also. I put buffered channel outside the function for synchronize execution, I also used channel receiver to assign and to stop channel.

func timeTick(flag bool, tick int,doneChan chan bool) {
    var tickChan *time.Ticker
    msg := make(<-chan time.Time) // channel receiver

    if flag {
        tickChan = time.NewTicker(time.Second * time.Duration(tick))
    }

    if !flag {
        doneChan <- true    
        <-msg
    }

    if tickChan != nil { // Check if nil
        msg = tickChan.C
    }

    for {
        select {
            case <-msg:
                fmt.Println("Ticker ticked ")
            case <-doneChan:
                fmt.Println("Done ")
                return
        }
    }
}

func main() {

    reader := bufio.NewReader(os.Stdin)
    doneChan := make(chan bool,1)
    for 
    {
        fmt.Print("> ")
        text, _ := reader.ReadString('
')
        text = strings.Replace(text, "
", "", -1)

        switch text {
        case "one":
            go timeTick(true, 1, doneChan)
        case "two":
            go timeTick(true, 2, doneChan)
        case "three":
            go timeTick(true, 3, doneChan)
        default:
            go timeTick(false, 0, doneChan)
        }
    }

}