触发和停止时间。手动Golang中的标记通道

时间:2018-01-17 22:38:56

标签: go

所以我有这个代码,它接受onetwothree的用户输入。它会根据所选的持续时间打印Ticker ticked。我需要有关如何在以不同的持续时间再次激活股票代码之前停止股票代码的帮助。

package main

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

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

    for {
        fmt.Print("> ")

        text, _ := reader.ReadString('\n')
        text = strings.Replace(text, "\n", "", -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
        }
    }
}

因此,用户输入onetwothree以激活其他代码,它会将true发送到doneChan频道。

当我使用one激活代码时。它每秒打印Ticker ticked但是当我在自动收报机运行时输入twothree时如何停止自动收报机?然后它引出了我的主要问题,为什么即使输入随机字符串也没有触发doneChan

2 个答案:

答案 0 :(得分:2)

您需要传入用于信号完成的频道。如果有的话,您总是希望取消当前的自动收报机,这样您就可以在主for循环的每次迭代中尝试发送。由于通道未缓冲,因此发送操作正在阻塞,因此您需要在具有默认情况的select语句中尝试发送,以防止在您没有当前自动收报机尝试从通道读取的情况下出现死锁

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('\n')
        text = strings.Replace(text, "\n", "", -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
        }
    }
}

答案 1 :(得分:0)

您也可以尝试以下代码。我把缓冲通道放在函数外部进行同步执行,我还使用通道接收器来分配和停止通道。

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('\n')
        text = strings.Replace(text, "\n", "", -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)
        }
    }

}