One of the gotchas in Go is that simply assigning slice values to another actually copies the values; what happens behind the scenes is you are copying reference (i.e., slice headers) to other slice’s backing array. This is because a slice acts as a view to the backing array and holds the reference to that array, and the length and capacity.
If your slice contains value types (e.g., string, int), you should use copy. But if it’s reference type like map, you need to perform a deep copy.
type A struct {
values []string
}
type B struct {
values []string
}
func main() {
x := A{values: []string{"a", "b", "c"}}
y := B{values: x.values} // shallow copy
z := B{values: make([]string, len(x.values))} // allocates space to be ready for copy
copy(z.values, x.values) // also shallow copy but safer
// x and y have the same backing array so their values are the same
// z has a different backing array and shows the same values as the other two
fmt.Printf("x: %+v\n", x.values) // x: [a b c]
fmt.Printf("y: %+v\n", y.values) // y: [a b c]
fmt.Printf("z: %+v\n", z.values) // z: [a b c]
// modify the first element
x.values[0] = "d"
// since x and y share the same backing array, their slices will show the same values
// z has a different backing array so it's not affected
fmt.Printf("x: %+v\n", x.values) // x: [d b c]
fmt.Printf("y: %+v\n", y.values) // y: [d b c]
fmt.Printf("z: %+v\n", z.values) // z: [a b c]
}