I am trying to build an array of functions that contain an enclosed variable (in this case a string) but I was getting some unexpected output. I figure the reason I am getting this output is because the func literal being appended is actually a pointer to code that is being changed after each iteration.
Is there a way to new()
or make()
a function type so that append()
will get a different function instance per iteration instead?
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
Outputs:
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
2014/11/23 18:13:16 world
Each iteration of the loop uses the same instance of the variable s
, so each closure shares that single variable. To bind the current value of s
to each closure as it is launched, one must modify the inner loop to create a new variable each iteration. For example,
package main
import "log"
var functions []func()
func main() {
for _, s := range [...]string{"goodbye", "cruel", "world"} {
s := s // create new s
functions = append(functions, func() {
log.Println(s)
})
}
for _, f := range functions {
f()
}
}
Output:
2009/11/10 23:00:00 goodbye 2009/11/10 23:00:00 cruel 2009/11/10 23:00:00 world
References: