It's weird in below Golang code that product of two time duration is zero in variable 'delay', but when print the product directly without through any variable, the output is as expected. Anyone can explain this?
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()
}
}
}()
}
The output is:
Go clean task: 0 5m0s
Update:
I also attempted to run following code, it works well.
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)
}
Update again:
Paul's answer is accepted. Actually StartCleanTask() is invoked in the init function of cfg package, and cfg.Config.Timeout is assigned to a specified value in main function. BUT I ignored that package's init() function is invoked implicitly before main(), so the variable delay is always ZERO.
BTW, I don't understand why some people give negative score to this question. I think others may hit similar problem, and this post should be helpful to the victim who don't really know the calling sequence between init() and main().
My guess is that you're updating cfg.Config.Timeout
concurrently to this task. Perhaps like this:
func main() {
StartCleanTask()
cfg.Config.Timeout = 300
...
}
This introduces a race, and it happens that in the goroutine inside StartCleanTask
, delay
is assigned before the Timeout
is initialized, and the fmt.Println
happens after the initialization.
You can use the race detector to see if this is the problem.
Assuming that cfg
is only initialized once, probably the right fix is to only start the cleanup task once the initialization has finished.