Private variable overridden in a loop

I am trying to build an array of functions containing a nested variable (in this case a string), but I am getting unexpected output. I understand the reason I am getting this output, because the func literal being added is actually a pointer to code that changes after each iteration.

Is there a way new()

or make()

for the function type to append()

instead get another instance of the function per iteration?

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

      

+3


source to share


1 answer


Each iteration of the loop uses the same variable instance s

, so each closure shares that single variable. To bind the current value s

to each closure as it runs, the inner loop needs to be modified to create a new variable on 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


Literature:

What happens to closures done as goroutines?

Capturing closure (for loop variable) in Go

+3


source







All Articles