Home > database >  Does taking the address of a slice element implies a copy of the element in Go?
Does taking the address of a slice element implies a copy of the element in Go?

Time:11-18

Let's say a Go 1.18 program has a quite heavy struct, for which copying is to be considered costly:

type MyStruct struct {
    P string
    // a lot of properties
}

Now let's define a function, taking a slice of such elements as input parameter, which goal is to update properties of each slice element:

func myFunc(sl []MyStruct) {
    for i := range sl {
        p := &sl[i]       // <-- HERE
        p.P = "bar"
        // other properties mutations
    }
}

At the <-- HERE mark, is the Golang compiler making a temporary copy of the slice element into the loop's scope, or is it taking the address of the slice element in-place?

The idea is to avoid copying the whole slice element.

A working example: https://go.dev/play/p/jHOC2DauyrQ?v=goprev

CodePudding user response:

&sl[i] does not copy the slice element, it just evaluates to the address of the ith element.

Slice elements act as variables, and &x evaluates to the address of the x variable. Think about it: since &sl[i] is the address of the ith element, the address does not need nor use the struct value, why would it make a copy?

If your slices are so big that you're worried about the performance impact of (implicit) copies, you really should consider storing pointers in the slice in the first place, and that way you can make your loop and accessing elements much simpler without having to worry about copies:

func myFunc(sl []*MyStruct) {
    for _, v := range sl {
        v.P = "bar"
        // other properties mutations
    }
}

Also note that if your slice holds non-pointers, and you want to change a field of a slice element, indexing the slice and referring to the field also does not involve copying the struct element:

func myFunc(sl []MyStruct) {
    for i := range sl {
        sl[i].P = "bar"
        // other properties mutations
    }
}

Yes, this may be more verbose and may be less efficient if you have to modify multiple fields (but compilers may also recognize and optimize the evaluation of multiple sl[i] expressions).

  • Related