Home > Backend Development > Golang > Go: Appending second item changes first item

Go: Appending second item changes first item

PHPz
Release: 2024-02-06 11:30:03
forward
642 people have browsed it

Go: Appending second item changes first item

Question content

I don’t know what to say, just look at the code and output. Code:

package main

import (
    "encoding/json"
    "fmt"
)

type Human struct {
    N string `json:"n"`
    C string `json:"c"`
}

func funcname(jDL ...[]byte) {
    jDL_len := len(jDL)
    people := [][]Human{}
    var buf []Human
    var err error
    for i := 0; i < jDL_len; i++ {
        err = json.Unmarshal(jDL[i], &buf)
        fmt.Println("buf", i, buf)
        people = append(people, buf)
        fmt.Println("people", i, people)
    }
    jsoned, err := json.Marshal(people)
    fmt.Println("jsoned", string(jsoned))
    fmt.Println("err", err)
}

func main() {
    i0 := []byte(`[
            {
                "n": "Alice",
                "c": "A1"
            },
            {
                "n": "Bob",
                "c": "A2"
            }
        ]`)
    i1 := []byte(`[
            {
                "n": "Clark",
                "c": "B1"
            },
            {
                "n": "Davis",
                "c": "B2"
            }
        ]`)
    funcname(i0, i1)
}
Copy after login

Output:

buf 0 [{Alice A1} {Bob A2}]
people 0 [[{Alice A1} {Bob A2}]]
buf 1 [{Clark B1} {Davis B2}]
people 1 [[{Clark B1} {Davis B2}] [{Clark B1} {Davis B2}]]
jsoned [[{"n":"Clark","c":"B1"},{"n":"Davis","c":"B2"}],[{"n":"Clark","c":"B1"},{"n":"Davis","c":"B2"}]]
err <nil>
Copy after login

View the people 0 and people 1 strings in the output. I use append to merge buf 0 and buf 1, so the people 1 string in the output should look like this: [[{Alice A1} {Bob A2}]] [{Clark B1} {Davis B2}], i.e. the first element of the array changes to the inserted element, although that shouldn't be the case. What could be the cause and how to fix it?

I didn't try any fixes as I didn't find any issues in the code.


Correct answer


While I agree with others' comments that the fix is ​​to move the buf variable inside the for loop, I also Believe this confusion stems from buf being a slice, and maybe the OP doesn't know how slicing works. Slices are different from arrays, as described in Go Slices: Usage and Internals.

slice

Key sentences quoting the source:

With this in mind, consider the following simplified example:

package main

import "fmt"

func main() {
    slice := [][]int{}
    buf := []int{0} // Slice

    for i := 0; i < 3; i++ {
        // Modifying the slice which is a pointer to an underlying array.
        buf[0] = i
        // Appending the slice (i.e. pointer).
        slice = append(slice, buf)
    }

    fmt.Println(slice)
}
Copy after login

Output: [[2] [2] [2]]

This is the behavior the OP observed in their example. Since slices are pointers to arrays, buf needs to be declared inside the for loop so that each iteration appends a different instance.

Now let's see what happens if we perform the same operation on an array.

Array

Key sentences quoting the source:

Now let's look at an example that demonstrates a copy consisting of the contents of an array when passing it (i.e. when passing it to append):

package main

import "fmt"

func main() {
    slice := [][1]int{}
    buf := [1]int{} // Array

    for i := 0; i < 3; i++ {
        // Modifying the array.
        buf[0] = i
        // Appending a copy of the array.
        slice = append(slice, buf)
    }

    fmt.Println(slice)
}
Copy after login

Output: [[0] [1] [2]]

Now, although the same buf variables are used in the for loop, all the values ​​are different.

The above is the detailed content of Go: Appending second item changes first item. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template