之间有什么区别吗?
ticker := time.NewTicker(1 * time.Second)
go func() {
for _ = range ticker.C {
fmt.Print("Tick")
}
}()
time.Sleep(3)
ticker.Stop()
和
var ticker *time.Ticker
go func() {
ticker = time.NewTicker(1 * time.Second)
for _ = range ticker.C {
fmt.Print("Tick")
}
}()
time.Sleep(3)
ticker.Stop()
就线程安全性而言,尤其是当函数中的工作时间超过刻度的时间时?
我问,因为(当不需要停止Ticker时)后者可以缩短为
go func() {
for ticker := time.NewTicker(1 * time.Second) ;; <-ticker.C {
fmt.Print("Tick")
}
}()
虽然前者不能。这种形式的另一个优点是可以立即触发第一个滴答。
答案 0 :(得分:2)
代码的第二个版本是错误的:它有竞争条件。
var ticker *time.Ticker
go func() {
ticker = time.NewTicker(1 * time.Second)
for _ = range ticker.C {
fmt.Print("Tick")
}
}()
time.Sleep(3)
ticker.Stop()
在goroutine内ticker
的分配与ticker
来电中使用ticker.Stop()
之间没有同步。
在实践中,由于长time.Sleep(3)
,这几乎总是无害的,但是如果可能的话应该避免这种比赛,因为即使它们今天无害,它们也可能在以后引起麻烦。例如,如果代替Sleep
你有一些代码需要花费不同的时间,那么如果代码恰好需要很短的时间,你可能会看到nil指针恐慌。
因此,我总是使用代码的第一个版本(在goroutine之外创建ticker
的代码)。
代码的第三个版本(其中ticker
完全在goroutine中使用)也很好。我绝对会使用这个较短版本的代码,如果可能的话,在goroutine中定义代码。代码的简洁性很好,但我也喜欢外面的代码根本看不到代码,所以代码的读者很容易理解代码的范围。