Home >Backend Development >Golang >Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?

Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-04 02:15:29914browse

Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?

Unexpected Slice Append Behavior

In Go, appending elements to a slice within a loop can unexpectedly alter the values of existing slices created from the same underlying array.

Problem Origin

The issue stems from the way slices reference the underlying array values. When you append to a slice, it may modify the existing array or create a new one. However, if the slice was created using the make function, it always references the same underlying array.

Example

Consider the following code:

<code class="go">func create(iterations int) []int {
    a := make([]int, 0)
    for i := 0; i < iterations; i++ {
        a = append(a, i)
    }
    return a
}

func main() {
    sliceFromLoop()
    sliceFromLiteral()
}

func sliceFromLoop() {
    i := create(11)
    j := append(i, 100)
    g := append(i, 101)
    h := append(i, 102)
    fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h)
}

func sliceFromLiteral() {
    i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    j := append(i, 100)
    g := append(i, 101)
    h := append(i, 102)
    fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h)
}</code>

In the sliceFromLoop function, all the new slices (j, g, h) share the same underlying array as the initial slice i. This means that when we append to i, it modifies the last element of all the other slices.

Solution

To avoid this behavior, it is recommended to make a copy of the slice before appending to it. The copy function allocates a new slice with the same elements as the original.

<code class="go">func sliceFromLoopFixed() {
    i := create(11)
    j := append([]int{}, i..., 100)
    g := append([]int{}, i..., 101)
    h := append([]int{}, i..., 102)
    fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h)
}</code>

In this case, the new slices j, g, and h have their own underlying arrays, so the value of i remains unaffected by the appends.

The above is the detailed content of Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn