Thanks, Marvin, I've learned a lot from your reply. And, I've written more code, like:
a, b, c := 1, 2, 3 > slice1 := []int{a, b, c} > for _, n := range slice1 { > go func(n *int) {fmt.Println(*n)}(&n) > } It seems that pass *n's address *in the code above will make a data race, which you have already explained why. But still, I have another question: If the coder do really want the addresses of elements in slice, how to do it correctly? Thanks. 2016-09-18 2:03 GMT+08:00 Marvin Renich <m...@renich.org>: > * 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 a topic in the > Google Groups "golang-nuts" group. > To unsubscribe from this topic, visit https://groups.google.com/d/ > topic/golang-nuts/yxhNl3Rnl6Y/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- 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.