在Golang代码中,两个持续时间的乘积在变量'延迟'中是奇怪的,但是当不通过任何变量直接打印产品时,输出是预期的。有谁能解释一下?
func StartCleanTask() {
go func() {
delay := cfg.Config.Timeout * time.Second
for {
fmt.Println("Go clean task: ", delay, cfg.Config.Timeout*time.Second)
select {
case <-time.After(cfg.Config.Timeout * time.Second):
clean()
}
}
}()
}
输出结果为:
Go clean task: 0 5m0s
更新
我还尝试运行以下代码,效果很好。
package main
import "fmt"
import "time"
func main() {
var timeout time.Duration
timeout = 100
delay := timeout * time.Second
fmt.Println("Go clean task: ", delay, timeout*time.Second)
}
再次更新:
保罗的回答被接受了。实际上,在cfg包的init函数中调用StartCleanTask(),并将cfg.Config.Timeout分配给main函数中的指定值。但是我忽略了在main()之前隐式调用了包的init()函数,因此变量delay总是为零。
顺便说一句,我不明白为什么有些人会对这个问题给出负面评分。我认为其他人可能遇到类似的问题,这篇文章应该对那些不太了解init()和main()之间的调用顺序的受害者有所帮助。答案 0 :(得分:2)
我的猜测是你正在同时更新cfg.Config.Timeout
这项任务。也许是这样的:
func main() {
StartCleanTask()
cfg.Config.Timeout = 300
...
}
这引入了一场比赛,并且在StartCleanTask
内的goroutine中,delay
在初始化Timeout
之前被分配,并且fmt.Println
在初始化之后发生
您可以使用race detector查看这是否是问题。
假设cfg
仅初始化一次,可能正确的修复只是在初始化完成后才启动清理任务。