Adeel Abbas
Adeel Abbas

Reputation: 55

Shallow copy of arrays for range loop in go

The following code

package main

import "fmt"

func main() {

    type Recording struct {
        Heartbeat string   `json:"heartbeat"`
        Videos    []string `json:"videos,omitempty"`
    }

    recordings := []Recording{}
    recordings = append(recordings, Recording{Heartbeat: "Blue", Videos: []string{"Foo"}})

    for _, recording := range recordings {
        recording.Videos[0] = "Bar"
    }

    fmt.Println(recordings)
}

outputs

[{Blue [Bar]}]

and not

[{Blue [Foo]}]

This means that the array in the temporarily created recording object actually gets shallow-copied and modifies the original array, although that might not be programmer's intention. This can lead to unintended bugs.

Is there a way to do deep copy on a range loop for slices.

Upvotes: 0

Views: 705

Answers (1)

Brian Pursley
Brian Pursley

Reputation: 1196

This is because slices are pointers to underlying arrays, so you need to implement your own deep copy function if you need a separate copy of the data.

Here is your example updated to make a copy of recordings:

package main

import "fmt"

func main() {

    type Recording struct {
        Heartbeat string   `json:"heartbeat"`
        Videos    []string `json:"videos,omitempty"`
    }

    recordings := []Recording{}
    recordings = append(recordings, Recording{Heartbeat: "Blue", Videos: []string{"Foo"}})

    // Make a copy
    other := make([]Recording, len(recordings))
    for i, r := range recordings {
        other[i] = Recording{
            Heartbeat: r.Heartbeat,
            Videos:    append([]string{}, r.Videos...),
        }
    }

    for _, recording := range other {
        recording.Videos[0] = "Bar"
    }

    fmt.Println(recordings)
    fmt.Println(other)
}

Output:

[{Blue [Foo]}]
[{Blue [Bar]}]

Upvotes: 0

Related Questions