Search code examples
gorace-conditionstatic-analysis

go vet: catches inner but not outer race-condition


In a recent question a nested loop was being used that led to a data-race. go vet only caught some of the problems.

Using a simplified version:

for _, o := range ol {
        o := o // <- remove this: `go vet` does *NOT* complain
        for _, d := range dl {
            d := d // <- remove this: `go vet` will complain
            go func() {
                fmt.Printf("%03d %03d\n", o, d) // potential data-race
            }()
        }
    }

Playground

go vet correctly detects the inner race-condition, but not the outer one.

Why is this? Too complex to keep track of scopes deeper than 2 levels?


Solution

  • A comment in the code says:

    This analyzer checks for references to loop variables from within a function literal inside the loop body. It checks only instances where the function literal is called in a defer or go statement that is the last statement in the loop body, as otherwise we would need whole program analysis.

    The go vet command does not complain about o because the go statement is not the last statement in the o loop.

    The test is very simple and probably detects most instances of the bug. Detecting other instances of the bug requires an approach that will take more time to develop and execute.