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.

Reply via email to