slice 相关一道题
package main
import (
"encoding/json"
"fmt"
)
type AutoGenerated struct {
Age int `json:"age"`
Name string `json:"name"`
Child []int `json:"child"`
}
func main() {
jsonStr1 := `{"age": 14,"name": "potter", "child":[1,2,3]}`
a := AutoGenerated{}
json.Unmarshal([]byte(jsonStr1), &a)
aa := a.Child
fmt.Println(aa) // output:[1,2,3]
jsonStr2 := `{"age": 12,"name": "potter", "child":[3,4,5,7,8,9]}`
json.Unmarshal([]byte(jsonStr2), &a)
fmt.Println(aa) // output: [3,4,5]
// fmt.Println(a.Child) // output: [3,4,5,7,8,9]
}
解释
type AutoGenerated struct {
Child []int
}
Then you do
a := AutoGenerated{} // (1)
jsonStr1 := `{"age": 14,"name": "potter", "child":[1,2,3]}`
json.Unmarshal([]byte(jsonStr1), &a) // (2)
aa := a.Child // (3)
fmt.Println(aa)
jsonStr2 := `{"age": 12,"name": "potter", "child":[3,4,5,7,8,9]}`
json.Unmarshal([]byte(jsonStr2), &a) // (4)
fmt.Println(aa)
So, what happens:
-
You create a variable, a, of type AutoGenerated which is initialized to the zero value for its type.
Because of that, its Child field, which is a slice, is initialized to the zero value for a slice which, among other things, means having no backing array.
-
You unmarshal a JSON document into a, and an array [1, 2, 3] from that documnent got unmarshaled into Child.
This made the slice allocate a backing array of enough capacity to hold the three element. Please note this.
-
You copy the slice value from the field Child into the variable aa.
A slice in Go is a struct of three fields: the capacity, the length and a pointer to (an address of) the backing array holding the slice’s contents. This is what is copied when you copy a slice value. Note that the backing array is not copied; only its address.
-
You unmarshal another JSON document into a. This time, a longer array gets unmarshaled into the slice in the Child field of a.
Since it contains twice as much elements Child held before unmarshaling, the code which did the unmarshaling had to reallocate the backing array of the slice: let’s cite the documentation:
To unmarshal a JSON array into a slice, Unmarshal resets the slice length to zero and then appends each element to the slice. As a special case, to unmarshal an empty JSON array into a slice, Unmarshal replaces the slice with a new empty slice.
Reallocation made a new fresh backing array and assigned its address to the slice value held in the Child field. Nothing had happened to the slice value in the aa variable: it continued to point to the old backing array.
小结
- slice 是个 struct
- 仅拷贝了 struct 的 data 字段
- 原文作者:战神西红柿
- 原文链接:https://tomatoares.github.io/posts/go/go-slice-Q/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。