A recent discussion in github has a question about an example “redefining loop variable semantics” – getting help

In a recent discussion on redefining for loop variable semantics, Rob gave an example and he thinks it is not necessary to copy a loop variable when it is an interface value. For convenience, the example and Rob’s statement are shown here:

 	for _, informer := range c.informerMap {
+		informer := informer
 		go informer.Run(stopCh)
 	}

Rob said,

one of these two changes is unnecessary And the other one is an actual bug fix, but you can’t tell which one without more context. (in one, The loop variable is an interface value, and copying it has no effect;

In fact, in my opinion, it is necessary even if the loop variable is an interface value. I did a test based on the following code.

type Inf interface {
	Get()
}


type S struct {
	name string
}

func (s *S) Get()  {
	fmt.Println(s)
	return
}

func main() {
	infs := []Inf{&S{name: "Alice"}, &S{name: "Bob"}}

	var wg sync.WaitGroup
    // i is an interface value
	for _, i := range infs {
		// i := i
		wg.Add(1)
		go func() {
			defer wg.Done()
			i.Get()
		}()
	}
	wg.Wait()
}

Without copying the loop variable to the local variable, the output is the following, which is false.

&{Bob}
&{Bob}

I may have misunderstood what Rob said. Can you please help me with the question what do you mean by “that loop variable is an interface value, and copying it has no effect”?


Leave a Comment