3 ms·
I'm learning a bit of go at the moment, and liking it a lot. One thing which caused me a little head scratching was doing something like this: for _, item
by jbert 14y ago
I'm learning a bit of go at the moment, and liking it a lot. One thing which caused me a little head scratching was doing something like this:
for _, item := range slice_of_obj {
item.update()
}
where the 'update' method wrote to some member data in item.
It seems that the 'item' is a copy of, rather than an alias to, the underlying object, so the mutating 'update' call is updating the copy, which is then discarded. (The 'right way' to do this to use the loop index and slice_of_obj[i], but that seems mildly barbaric)
This seemed odd to me, particularly since no error was generated. Can anyone comment if I'm doing anything particularly dumb here? If Go had a concept of 'const', at least it could throw an error when you mutate the copy which is going to be discarded.
- densh 14y agoIMO The right way is to have a slice filled with pointers rather than bare structs: https://gist.github.com/2975397 https://gist.github.com/2975397 Btw code that uses range will always be faster than alternative with for loop and indexing (obj[i]) as range-based code can be optimized by Go compiler not to perform any bound checks.
- jbert 14y agoYes, that works nicely, thanks. But sometimes (rarely) you do want a contiguous bunch of objects, rather than have the indirection. I think ideally, it would work (as an alias) but if not, I think it should error. Or maybe this is a FAQ, with a good rationale, which I just haven't got to yet.
- drivebyacct2 14y agoI've been burnt by it as well, I didn't read the spec closely enough apparently. I would love to see it called out in an example.
- jgrahamc 14y agoThe effect you are seeing there is because the as it says in the documentation: "The iteration values are assigned to the respective iteration variables as in an assignment statement." So item is being assigned and because it's an obj and not a *obj you are getting a copy. Whereas slice_of_obj[i] is accessing the element within the slice without a copy. One solution to this problem would be to store pointers in your slice instead of objects.
- jbert 14y agoThanks for the reply. I don't argue that it's not to spec, just that it seems not useful/a bit surprising. Some other languages (e.g. perl and I think also java) choose to make the loop var an alias, rather than a copy, to allow mutation: for my $item (@items) { $item->frob; # Can happily mutate the item } will work as it reads.