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:
What happens with closures running as goroutines?
Captured Closure (for Loop Variable) in Go
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With