Go 的array,slice,map一直不太分的清楚,做个学习笔记。

Array

array 就是数组

数组定义

var arr [n]type   #n表示长度,type表示数组类型

示例

var arr [3]int   # 申明一个长度为3的整形数组,arr[0],arr[1],arr[2] 都是0

数组还有一种方法定义:

a := [2]int{1,2}
b := [10]int{1,2,3} # b[0] 等于1 b[1] 等于2 b[2] 等于 3,其它都默认等于0
c := [...]int{4, 5, 6}  # go自动根据数组元素计算长度,不等于动态都,只是go默认计算了长度

多维数组根其它类型语言一样,也是嵌套,多了个内层数组的长度定义

doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}

slice

在很多应用场景里面,数组不能满足需求,我们在使用初始化的时候可能不知道需要多大,slice类似于动态数组,但不是真正但动态数组。

slice是一个引用类型,指向底层的一个数组。

我们申明slice可以像数组那样,只是不要定义长度

var slices []int

示例

slice := []byte {'a', 'b', 'c', 'd'}

slice 可以从一个数组或一个已经存在的 slice 中再次声明。slice 通过 array[i:j] 来获取,其中i是数组的开始位置,j 是结束位置,但不包含 array[j],它的长度是 j-i

var arr = [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

var a, b []byte  #声明两个含有 byte 的 slice

a = ar[2:5]  #现在 a 含有的元素: ar[2]、ar[3]和ar[4]

b = ar[3:5]  # b 的元素是:ar[3] 和 ar[4]

slice简要写法

slice 的默认开始位置是 0,ar[:n] 等价于 ar[0:n]
slice 的第二个序列默认是数组的长度,ar[n:] 等价于 ar[n:len(ar)]
如果从一个数组里面直接获取 slice,可以这样 ar[:],因为默认第一个序列是 0,第二个是数组的长度,即等价于 ar[0:len(ar)]

示例

var arr = [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var a, b, c []byte
a = arr[3:]  #[4 5 6 7 8 9 10]
b = arr[:]  #[1 2 3 4 5 6 7 8 9 10]
c = arr[:4] #[1 2 3 4]

slice 中取slice

var arr = [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var a, b []byte
a = arr[3:] #[4 5 6 7 8 9 10]
b = a[2:5] #[6 7 8]

slice 是引用类型,所以当引用改变其中元素的值时,其它的所有引用都会改变该值,例如上面的 a 和 b,如果修改了 a 中元素的值,那么 b 相对应的值也会改变。

slice的几个内置函数

len 获取 slice 的长度
cap 获取 slice 的最大容量
append 向 slice 里面追加一个或者多个元素,然后返回一个和 slice 一样类型的 slice
copy 函数 copy 从源 slice 的 src 中复制元素到目标 dst,并且返回复制的元素的个数

append 函数会改变 slice 所引用的数组的内容,从而影响到引用同一数组的其它 slice。但当 slice 中没有剩余空间(即 (cap-len) == 0 )时,此时将动态分配新的数组空间。返回的 slice 数组指针将指向这个空间,而原数组的内容将保持不变;其它引用此数组的 slice 则不受影响。

Map

map 也就是 Python 中字典的概念,它的格式为 map[keyType]valueType

map 的读取和设置也类似 slice 一样,通过 key 来操作,只是 slice 的 index 只能是 int 类型,而 map 多了很多类型,可以是 int,可以是 string 及所有完全定义了 == 与 != 操作的类型。

map的申明,有两种方式

var numbers map[string]int
numbers := make(map[string]int)
numbers := map[string]int{"a":3,"b":5} #初始化赋值

几个要点:

map 是无序的,每次打印出来的 map 都会不一样,它不能通过 index 获取,而必须通过 key 获取
map 的长度是不固定的,也就是和 slice 一样,也是一种引用类型
内置的 len 函数同样适用于 map,返回 map 拥有的 key 的数量
map 的值可以很方便的修改,通过 numbers["one"]=value 可以很容易的把 key 为 one 的字典值改为 value
map 和其他基本类型不同,它不是 thread-safe,在多个 go-routine 存取时,必须使用 mutex lock 机制

map是引用类型,如果两个 map 同时指向一个底层,那么一个改变,另一个也相应的改变