Home  >  Article  >  Backend Development  >  Why Does Appending to a Slice in a Loop Affect Other Slices in Go?

Why Does Appending to a Slice in a Loop Affect Other Slices in Go?

Barbara Streisand
Barbara StreisandOriginal
2024-11-06 04:05:02962browse

Why Does Appending to a Slice in a Loop Affect Other Slices in Go?

Unexpected Behavior in Slice Append: How to Create Multiple Slices Without Modification Concerns

When manipulating slices in Go code, you may encounter a puzzling issue: appending elements to a slice within a loop and then using the loop result to create new slices can result in the last append overriding the slices from previous appends. This behavior arises because the slices reference the same underlying array values.

Example:

<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 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)
}</code>

In this example, the sliceFromLoop function creates a slice i and appends different values to it, resulting in the slices j, g, and h. However, all three slices point to the same underlying array, so when the last append modifies the array, it affects all slices.

Solution: Copying Slices for Independent Modifications

The idiomatic way to create multiple slices based on an existing slice and avoid modification concerns is by copying the slice before appending anything. This ensures that each new slice has its own underlying array.

<code class="go">func makeFromSlice(sl []int) []int {
    result := make([]int, len(sl))
    copy(result, sl)
    return result
}</code>

Example Usage:

<code class="go">func main() {
    i := make([]int, 0)
    for ii := 0; ii < 11; ii++ {
        i = append(i, ii)
    }
    j := append(makeFromSlice(i), 100) // works fine
}</code>

In this revised example, we create a copy of the i slice before appending 100 to it. This ensures that j references a separate underlying array and won't be affected by future modifications to i.

Explanation of Slice Literal Behavior

The reason why this issue does not arise with slice literals (e.g., i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) is that a new array is allocated if the append operation would exceed the capacity of the backing array. This behavior is unrelated to slice literals and is a fundamental property of appending to slices.

The above is the detailed content of Why Does Appending to a Slice in a Loop Affect Other Slices 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