golang make的使用

make函数用于初始化slice、chan和map
如果只用var声明,不用make初始化,变量对应的值为nil。

1.make初始化slice
共有三个参数:类型,长度和容量,其中类型和长度必须指定。
在这里插入图片描述
关于长度和容量,指定长度len,即为slice赋指定长度的默认值,比如int赋值0,string赋值"",bool赋值false等。并且0到len-1都是合法的下标访问范围。
golang make的使用_第1张图片
在这里插入图片描述
容量表示slice底层数组的长度,当使用append操作进行追加时,如果追加后的底层数组长度大于了当前容量cap,那么就会重新分配另一块连续内存给当前的底层数组,并把之前的复制过来。若不声明容量,则默认容量等于当前长度len。

切片是基于数组的。可以把切片简单的理解为数组中的一段,它保留了指向数组中某个元素(可以不是第一个元素)的指针,以及它本身的长度(也就是切片的大小)。
var s=make([]int,0,10)这条语句创建了一个长度为10的数组,并在该数组之上建立了一个切片s,该切片保留指向数组第一个元素的指针,以及它的长度(0)。

下面是demo示例:

//s的地址0xc0002fe000  s:[0 0 0 0 0], len:5,cap:6,底层数组长度为5,最大连续长度为6,返回一个[0:5]的切片
	s:=make([]int,5,6)
	fmt.Printf("%p\n",s)
	fmt.Println(s)
	fmt.Println(len(s),cap(s))

	//b的地址0xc0002fe000  s不变,append到切片s的下一位(底层数组第6位) len:6,cap:6,底层数组长度为6,返回一个[0:6]的切片
	b:=append(s,6)
	fmt.Printf("%p\n",b)
	fmt.Println(b)
	fmt.Println(len(b),cap(b))

	//c的地址0xc0002fe000  s不变,append到切片s的下一位(底层数组第6位) len:6,cap:6,底层数组长度为6,返回一个[0:6]的切片
	c:=append(s,7)
	fmt.Printf("%p\n",c)
	fmt.Println(c)
	fmt.Println(len(c),cap(c))

	//切片b[0:6],超过底层数组的cap,所以在b后面追加一个元素底层数组会进行扩容,扩容后cap的为原来的两倍,并且底层数组的首地址改变,返回一个[0:7]切片
	d:=append(b,7)
	fmt.Printf("%p\n",d)
	fmt.Println(d)
	fmt.Println(len(d),cap(d))
	
	//切片s根本没有变过,因为它引用的底层数组[0:5]没有变过
	fmt.Printf("%p\n",s)
	fmt.Println(s)
	fmt.Println(len(s),cap(s))

打印结果:
0xc00002a0f0
[0 0 0 0 0]
5 6
0xc00002a0f0
[0 0 0 0 0 6]
6 6
0xc00002a0f0
[0 0 0 0 0 7]
6 6
0xc000092060
[0 0 0 0 0 7 7]
7 12
0xc00002a0f0
[0 0 0 0 0]
5 6

2.make初始化map
make初始化map时,可以指定map的容量,也可以不指定。而且可以看到指定map的容量对map的初始大小是没有什么关系的。

	m:=make(map[string]int)
	m1:=make(map[string]int,2)
	fmt.Println(m,len(m)) //map[] 0
	fmt.Println(m1,len(m1))  //map[] 0

可以看到map的大小随着添加的kv对增多而变大

	m1:=make(map[string]int,2)
	fmt.Println(m1,len(m1)) //map[] 0
	m1["1"]=1
	fmt.Println(m1,len(m1)) //map[1:1] 1
	m1["2"]=2
	fmt.Println(m1,len(m1))  //map[1:1 2:2] 2

你可能感兴趣的:(go)