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 <[email protected]>:
> * Fei Ding <[email protected]> [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
> [email protected].
> 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 [email protected].
For more options, visit https://groups.google.com/d/optout.