简体   繁体   中英

Copying arrays to slices in Go

Please can you help me understand how generating a slice from an array works. Why are ID1 and ID2 not the same?

    a := [2]string{"a", "b"}
    b := [2]string{"c", "d"}
    var z [2][2]string
    z[0] = a
    z[1] = b

    fmt.Printf("%s\n", z)
    var id [][]string
    for _, t := range z {
        temp := t[:]
        id = append(id, temp)
    }
    fmt.Printf("\nid1 = %s", id)

    var id2 [][]string
    for _, t := range z {
        temp := t
        id2 = append(id2, temp[:])
    }
    fmt.Printf("\nid2 = %s", id2)

[[ab] [cd]]

id1 = [[cd] [cd]]
id2 = [[ab] [cd]]

Because the for range loop has a single iteration variable which is reused in each iteration. Spec: For statements: For statements with for clause

Variables declared by the init statement are re-used in each iteration.

So in your first loop:

for _, t := range z {
    temp := t[:]
    id = append(id, temp)
}

There is a single t , and you slice the same t array, so each temp slice you append, it will point to the same backing array, which is t , and it is overwritten in each iteration, so its value will be the value of the last iteration: [cd] .

In your second loop:

for _, t := range z {
    temp := t
    id2 = append(id2, temp[:])
}

Also there is a single t iteration variable, but you make a copy of it: temp := t , and you slice this copy, which is detached from t , and you append a slice that has the copy as its backing array, which will not be overwritten in each iteration.

This is the problematic assignment. It is not what it seems:

temp := t[:]

Here, t is an array and the loop variable. That means at each iteration, the contents of the current array is copied onto t . At the first iteration, t=[]string{"a","b"} , and a slice is created to point to this array and assigned to temp . At the second iteration t is overwritten to become []string{"c","d"} . This operation also overwrites the contents of the first slice. So, you end up with the {{"c","d"},{"c","d"}} . The important point here is that contents of t gets overwritten, and t is shared between the two slices.

In the first loop you are saving slices which have the same backing array (ie. the loop variable t ). In the second loop you are storing slices using different backing arrays since you make a copy of t in temp .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM