Golang Pitfalls

Caveat: Capturing Iteration Variables

Example 1: creating a new func in a loop

From Section: 5.6.1 in “The Go Programming Language”

var rmdirs []func()

for _, d := range tempDirs() {
	dir := d // NOTE: necessary! create a new local variable to capture the value
	os.MkdirAll(dir, 0755)
	rmdirs = append(rmdirs, func() {
		os.RemoveAll(dir)
	})
}


// do some work ...

for _, rmdir := range rmdirs {
	rmdir() // clean up
}

If we don’t have dir := d, all dirs will be the last value of d in tempDirs().

Example 2: thumbnail image, passing value as an explict argument to anonymous func

From Page 235 of “The Go Programming Language”

// correct!
func makeThumbnails3(filenames []string) {
	ch := make(chan struct{})
	for _, f := range filenames {
		go func(f string) {
			thumbnail.ImageFile(f)
		}(f) // here is important
	}

	// wait for goroutines to complete
	for range filenames {
		<- ch
	}

}

Notice that we passed the value of f as an explicit argument to the literal function instead of using the declaration of f from the enclosing for loop:

// incorrect!
for _, f := range filenames {
	go func() {
		thumbnail.ImageFile(f) // NOTE: incorrect!
	}()
}