自动售票机是否通过其自动售票机告诉goroutine它已停止?

自动售票机是否通过其自动售票机告诉goroutine它已停止?,go,channel,goroutine,Go,Channel,Goroutine,我想,当我调用ticker.Stop,ticker.C时,应该告诉goroutine它已经结束了,因此for循环应该结束,但看起来不是这样,字符串ticker stopped从未打印过。正如JimB指出的,当时的文档。ticker指定Stop不会关闭通道,以防止从通道读取错误。你最好的选择可能是退出频道 package main import "fmt" import "time" func main() { ticker := time.NewTicker(time.Millisec

我想,当我调用ticker.Stop,ticker.C时,应该告诉goroutine它已经结束了,因此for循环应该结束,但看起来不是这样,字符串ticker stopped从未打印过。

正如JimB指出的,当时的文档。ticker指定Stop不会关闭通道,以防止从通道读取错误。你最好的选择可能是退出频道

package main
import "fmt"
import "time"

func main() {
    ticker := time.NewTicker(time.Millisecond * 500)
    go func() {
        for t := range ticker.C {
            fmt.Println("Tick at", t)
        }
        fmt.Println("ticker stopped")
    }()
    time.Sleep(time.Second * 5)
    ticker.Stop()
    time.Sleep(time.Second * 5)
}

从文档中可以看出:Stop不关闭频道抱歉,但我不太理解Stop不关闭频道的原因。我知道你已经解释过了-为了防止通道读取错误,但它仍然让我困惑。@幸运的是,这个API设计怪癖是在过去提出的,它看起来是一个实现问题。更多细节请参见。假设你在某个地方做了一件我所看到的非常奇怪的事情。Ticking是一个循环过程,因此使用I:=range ticket.C而不是t=I concur是合乎逻辑的,但后一种用法有时可能使用不当,并且现有的包是按照这种预期编码的。不幸的是,由于这个原因,这种行为几乎肯定不会改变,至少在Go2.0之前不会改变。
package main

import "fmt"
import "time"

func main() {
    ticker := time.NewTicker(time.Millisecond * 500)
    quit := make(chan struct{})
    go func() {
        for {
            select {
            case t := <-ticker.C:
                fmt.Println("Tick at", t)
            case <-quit:
                fmt.Println("ticker stopped")
                return
            }
        }
    }()
    time.Sleep(time.Second * 5)
    ticker.Stop()
    close(quit)
    time.Sleep(time.Second * 5)
}