* Fei Ding <fding...@gmail.com> [160916 23:30]: > Link here: https://play.golang.org/p/cdryPmyWt5 > > The code above is going to check the differences between pointers and > values in a for loop, while go statement is also used at the same time. For > code: > > values := []field{{"one"},{"two"},{"three"}} > for _, v := range values { > go v.print() > } > > we know that the console will print *three three three* as result, because > for loop runs into its end before go routines start executing, which write > *v* as the last element of the slice. But what about pointers? > > poniters := []*field{{"one"},{"two"},{"three"}} > for _, v := range poniters { > go v.print() > } > > It seems to print* one two three*, why?
Try running your example with the race detector. Then try commenting out, on separate trials, each of the two cases, again running under the race detector. The second case runs without a race, but the first does not. To understand why, you must carefully analyze what is happening according to the Go specification (https://golang.org/ref/spec#Go_statements). In the both cases, the variable v is reused for all iterations of the for loop; that is, every iteration of the loop uses the same variable v, but with a different value for each iteration. Now, in the first case, v is of type field. The go statement evaluates the function value and parameters. Evaluating the function value means, essentially, getting a pointer to the function to be called (this is a simplification, but is accurate enough for this analysis); it does not yet call the function. A method call can be thought of as a function call with the receiver as an implied first argument. So the first, implied, argument is evaluated as &v (because, according to the spec, x.m() is shorthand for (&x).m() in this scenario). The go statement creates a new goroutine with this particular function call, with the address of v as the first argument, to be executed at the go scheduler's discretion. Next, the for loop assigns the next element from the slice values to the variable v. This is the data race. There is no guarantee that the scheduler will wait for the sleep statement after the loop to start executing the first goroutine, and in fact it didn't on one run on my system; I got a result of two three three. There is no synchronization between the assignment to v by the for loop and the reference of v.name in v.print, so you have a data race. In the second case, v is of type *field. The go statement evaluates the first, implied, argument as the current value of v (the first pointer in the slice). The go statement creates a goroutine with a call to the print method with that value as the argument. When the for loop assigns the next element from the slice to v, it is not changing anything that is being referenced by the go routine, so there is no data race (and the values printed are taken from successive slice elements). ...Marvin -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.