【问题标题】:Triggering and stopping time.Ticker channel in Golang manually手动触发和停止时间。Golang 中的 Ticker 通道
【发布时间】:2018-01-18 21:51:48
【问题描述】:

所以我有这个代码,它接受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 来激活代码,否则它将发送truedoneChan 频道。

当我使用one 激活代码时。它每秒打印一次Ticker ticked,但是当我在代码运行时输入twothree 时如何停止代码?然后它把我带到了我的主要问题,为什么doneChan 甚至输入随机字符串都没有触发?

【问题讨论】:

  • 你不能在同一个 goroutine 中的频道 doneChan 上发送和接收。我建议从主 goroutine 发送 done 信号。
  • 您是否期望对 timeTick 的单独调用以某种方式从另一个 goroutine 执行 doneChan &lt;- true
  • @JimB 是的,就是这个想法。
  • @dev.bmax 我的代码需要更改什么?你能告诉我怎么做吗?
  • @Jahm:您对事情的工作方式有一些广泛的误解,但简而言之,您将希望将控制通道作为参数或闭包传递到您的函数中。

标签: go


【解决方案1】:

您需要传入用于表示完成的通道。如果有当前代码,您总是希望取消当前代码,因此您可以在主 for 循环的每次迭代中尝试发送。由于通道未缓冲,发送操作被阻塞,因此您需要在选择语句中使用默认情况尝试发送,以防止在您没有当前代码尝试从通道读取的情况下出现死锁.

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
        }
    }
}

【讨论】:

    【解决方案2】:

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

    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)
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 2017-10-03
      相关资源
      最近更新 更多