Reputation: 5086
I'm new to Golang and I recently had the same problem as described in this question: Strange golang "append" behavior
So I'm wondering if it's basically never appropriate to use the object copy in the for range
loop in anything outside of the scope of that loop– like passing it to a separate function, appending it (as described in the question), and so on.
Is it almost always more appropriate to access an object like this if you plan on mutating it, adding it to a list outside of the scope of that loop, and so on, because on the next loop the pointer you added will change?
for index := range myList {
doSomething(&myList[index])
}
Upvotes: 4
Views: 3239
Reputation: 6284
You mostly need to keep in mind that Go is pass by value. IF you are perfectly ok using a copy, fully understanding that mutations won't reflect, and that copies of huge structs can be costly, there are perfectly valid reasons for passing either a copy or a pointer.
If you need to make modifications, either pass by reference as you show here, or you can also store them as pointers in the slice to start with e.g. []*MyStruct
. Actually, that brings to light a design choice where they chose specifically in the spec to pass a struct by copying.
Under the covers, a slice
abstracts an array, but is merely a struct, known as a slice header, with a pointer to the array. When you pass a slice around, the header is passed by value, but the contents basically consist of 3 integers, so it's not expensive to copy it. This is the reason you have to reassign the variable when using append for it to persist, e.g. s = append(s, value)
. You can pass a slice around in your code by reference, but doing so isn't idiomatic Go.
Upvotes: 9