为了账号安全,请及时绑定邮箱和手机立即绑定

Golang 变量中两个持续时间的乘积为零

Golang 变量中两个持续时间的乘积为零

Go
慕雪6442864 2021-12-20 15:13:33
在下面的 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只初始化一次,可能正确的解决方法是在初始化完成后才启动清理任务。


查看完整回答
反对 回复 2021-12-20
  • 1 回答
  • 0 关注
  • 140 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号