Why is infinite loop not incrementing integer?

Viewed 133

This prints 0.

But when I add empty fmt.Println() in for loop its prints non zero value. Any ideas why?

GOMAXPROCS=1 ./foo
0
package main

import (
    "log"
    "os"
    "time"
)

func main() {
    var i uint64
    t := time.AfterFunc(time.Second*1, func() {
        log.Println(i)
        os.Exit(0)
    })
    defer t.Stop()

    for {
        i++
    }
}
1 Answers

You have a data race: you access the same variable from multiple goroutines without synchronization. The results are undefined. Use proper synchronization.

It's true that you don't launch goroutines in your code, but quoting from time.AfterFunc():

AfterFunc waits for the duration to elapse and then calls f in its own goroutine.

So you have the main goroutine incrementing (writing) the variable i, and you'll have another goroutine executing the function you pass to time.AfterFunc() which will read i.

Example to use synchronization:

var (
    mu sync.Mutex
    i  uint64
)
t := time.AfterFunc(time.Second*1, func() {
    mu.Lock()
    log.Println(i)
    mu.Unlock()
    os.Exit(0)
})
defer t.Stop()

for {
    mu.Lock()
    i++
    mu.Unlock()
}
Related