Table of Contents |
---|
提出问题
- 对一个slice的操作什么时候会影响别的slice,什么时候不会?
- 遍历slice的时候需要注意什么?
- slice元素的类型该不该用指针?
- 遍历map的时候需要注意什么?
- map的value类型该不该用指针?
- 为什么slice的元素可以取地址,而map的value却不可以?
...
一个slice由三部分构成: ptr(指向array的指针), len(当前大小), cap(最大容量)。
Code Block | ||
---|---|---|
| ||
a := [4]int{1, 2, 3, 4} fmt.Printf("a: %v\n", a) s1 := a[:2] fmt.Printf("s1 = a[:2]\n") fmt.Printf("s1: %v\n", s1) fmt.Printf("s1.len: %v\n", len(s1)) fmt.Printf("s1.cap: %v\n", cap(s1)) s2 := a[1:] fmt.Printf("s2 = a[1:]\n") fmt.Printf("s2: %v\n", s2) fmt.Printf("s2.len: %d\n", len(s2)) fmt.Printf("s2.cap: %d\n", cap(s2)) s1[1] = 0 fmt.Printf("s1[1] = 0\n") fmt.Printf("a: %v\n", a) fmt.Printf("s1: %v\n", s1) fmt.Printf("s2: %v\n", s2) fmt.Printf("&a[1]: %p\n", &a[1]) fmt.Printf("&s1[1]: %p\n", &s1[1]) fmt.Printf("&s2[0]: %p\n", &s2[0]) 输出: a: [1 2 3 4] s1 = a[:2] s1: [1 2] s1.len: 2 s1.cap: 4 s2 = a[1:] s2: [2 3 4] s2.len: 3 s2.cap: 3 s1[1] = 0 a: [1 0 3 4] s1: [1 0] s2: [0 3 4] &a[1]: 0xc420012288 &s1[1]: 0xc420012288 &s2[0]: 0xc420012288 对一个array进行slicing操作得到的slice指向该array。 对一个slice进行slicing得到新的slice与原slice指向同一个array。 此时这个两个slice对它们的重叠部分的元素进行写操作是会互相影响的,因为它们操作的是同一个array。 |
...
slice是基于array实现的,且array是暴露给开发者的(例如对array进行slicing操作获得slice)。array可以取元素地址,slice很自然也可以。
map的内部结构没有直接暴露给开发者的。当map进行扩容时,会将原有的key/value重新hash并拷贝到新的空间,Golang为了避免开发者对旧空间的访问,因此不给开发者任何获取value地址的机会。
参考资料
- https://blog.golang.org/go-slices-usage-and-internals
- https://blog.golang.org/go-maps-in-action
- https://www.goinggo.net/2013/12/macro-view-of-map-internals-in-go.html
...