Skip to content

Instantly share code, notes, and snippets.

@komuw
Created November 5, 2020 13:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komuw/62f53f27fd5bd2ff77c6b8b61631f6be to your computer and use it in GitHub Desktop.
Save komuw/62f53f27fd5bd2ff77c6b8b61631f6be to your computer and use it in GitHub Desktop.
Golang variable shadowing can mask race conditions
package main
import "time"
type cool struct{}
func (c *cool) add() error {
return nil
}
func main() {
c := &cool{}
err := c.add()
if err != nil {
panic(err)
}
go func() {
for i := 0; i < 6; i++ {
err = c.add()
if err != nil {
panic(err)
}
}
}()
err = c.add()
if err != nil {
panic(err)
}
time.Sleep(4 * time.Second)
}
@komuw
Copy link
Author

komuw commented Nov 5, 2020

gofmt -s -w .; go run --race .

==================
WARNING: DATA RACE
Write at 0x00c0001120b0 by goroutine 6:
  main.main.func1()
      /tmp/cooler/main.go:21 +0x58

Previous write at 0x00c0001120b0 by main goroutine:
  main.main()
      /tmp/cooler/main.go:28 +0xf2

Goroutine 6 (running) created at:
  main.main()
      /tmp/cooler/main.go:19 +0xe4
==================

As you can see, the race has nothing to do with the add method. Rather, the err variable which is shadowed is now been written(assigned) to by different goroutines.

And go vet -all ./... does not catch it.
Neither does

gobin -u golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow && \
go vet -vettool=$(which shadow) -strict ./...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment