在下面的 Golang 代码中奇怪的是,变量 'delay' 中两个持续时间的乘积为零,但是当不通过任何变量直接打印乘积时,输出符合预期。任何人都可以解释这一点? 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)}再次更新:保罗的回答被接受。实际上StartCleanTask()是在cfg包的init函数中调用的,cfg.Config.Timeout在main函数中被赋值为一个指定的值。但是我忽略了该包的 init() 函数在 main() 之前隐式调用,因此变量延迟始终为零。顺便说一句,我不明白为什么有些人对这个问题给出负分。我认为其他人可能会遇到类似的问题,这篇文章应该对不真正了解 init() 和 main() 之间调用顺序的受害者有所帮助。
1 回答

拉丁的传说
TA贡献1789条经验 获得超8个赞
我的猜测是您正在cfg.Config.Timeout同时更新此任务。也许像这样:
func main() {
StartCleanTask()
cfg.Config.Timeout = 300
...
}
这就引入了一个竞争,恰好在 goroutine 里面StartCleanTask,delay在Timeout初始化之前被赋值,而fmt.Println在初始化之后发生。
您可以使用竞态检测器来查看这是否是问题所在。
假设cfg只初始化一次,可能正确的解决方法是在初始化完成后才启动清理任务。
- 1 回答
- 0 关注
- 140 浏览
添加回答
举报
0/150
提交
取消