Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

提出问题

  1. 对一个slice的操作什么时候会影响别的slice,什么时候不会?
  2. 遍历slice的时候需要注意什么?
  3. slice元素的类型该不该用指针?
  4. 遍历map的时候需要注意什么?
  5. map的value类型该不该用指针?
  6. 为什么slice的元素可以取地址,而map的value却不可以?

...

一个slice由三部分构成: ptr(指向array的指针), len(当前大小), cap(最大容量)。

Image Removed

Image Removed


Code Block
languagebash
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地址的机会。


参考资料

  1. https://blog.golang.org/go-slices-usage-and-internals
  2. https://blog.golang.org/go-maps-in-action
  3. https://www.goinggo.net/2013/12/macro-view-of-map-internals-in-go.html

...