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!
}()
}