Range over addressable arrays

458 views
Skip to first unread message

Matthew Dempsky

unread,
Oct 13, 2017, 7:02:06 PM10/13/17
to golang-dev
Is there background on why ranging over an addressable array makes a copy of that array rather than iterating over the original?

I know it's possible to replace "range x" with "range &x", but the only time the latter actually appears in the standard repo is within $GOROOT/test. On the other hand, running github.com/mdempsky/rangerdanger against std+cmd yields 90 hits.

Is this something:

  - we should be addressing in the standard repo?
  - we should add a vet or lint check for?
  - worth trying to change for Go 2?

Rob Pike

unread,
Oct 13, 2017, 7:14:39 PM10/13/17
to Matthew Dempsky, golang-dev
I don't remember the discussion, but I believe the idea for the range loop was that loop parameters were evaluated once, and copies of the iteration are required to guarantee that original evaluation stays valid. I feel this is consistent with the by-value semantics used everywhere in Go (and in every other C family language).

This code would work differently if the rule changed. See the contrived but legal https://play.golang.org/p/rOrcsLrf-W.

Changing that behavior sounds dangerous as it removes a guarantee, but if the compiler could promise that the initial evaluation was sufficient, it could avoid the copy for efficiency.

-rob


--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joe Tsai

unread,
Oct 14, 2017, 11:54:28 AM10/14/17
to golang-dev
compress/flate had a performance issue because it was ranging over an array: #18625

As a result, I proposed adding a vet check for it (#18626), but it didn't meet the requirements for vet.

JT
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.

Russ Cox

unread,
Oct 14, 2017, 10:43:24 PM10/14/17
to Rob Pike, Matthew Dempsky, golang-dev
On Fri, Oct 13, 2017 at 7:14 PM, Rob Pike <r...@golang.org> wrote:
I don't remember the discussion, but I believe the idea for the range loop was that loop parameters were evaluated once, and copies of the iteration are required to guarantee that original evaluation stays valid. I feel this is consistent with the by-value semantics used everywhere in Go (and in every other C family language).

Yes. I'm not even sure there was an explicit discussion originally (there certainly have been since), because it follows from the fact that the range loop is defined to evaluate its argument once before the loop executes. Sometimes the argument is large, of course. 

Note that there's already an optimization for the range loop when only the index is ranged over, not the values.

Someone on the Go team at Google (I don't remember who, sorry!) pointed out to me in just the past week or so that instead of range &x as the fix, we should probably be suggesting range x[:], which requires much less explanation. I agree with that.

Please do file a short experience report for Go 2, listing the hits you found in std+cmd. It would especially help to catalog the impact (slower code, actually needed, etc). Right now, it's only worth fixing the ones that are causing real problems.

Thanks.
Russ

a.val...@gmail.com

unread,
Oct 28, 2017, 7:27:00 PM10/28/17
to golang-dev
> Changing that behavior sounds dangerous as it removes a guarantee, but if the compiler could promise that the initial evaluation was sufficient, it could avoid the copy for efficiency.

There is the corresponding issue -
https://github.com/golang/go/issues/19817
Reply all
Reply to author
Forward
0 new messages