go语言中的new与make
初学go语言,对于初始化变量时使用new还是make有些迷惑,这里简单总结一下
new() 和 make() 的区别
以下摘录自 https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/07.2.md
二者都在堆上分配内存,但是它们的行为不同,适用于不同的类型。
- new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于
&T{}
。 - make(T) 返回一个类型为 T 的初始值,它只适用于3种内建的引用类型:切片、map 和 channel
换言之,new 函数分配内存,make 函数初始化;下图给出了区别:
我的理解,new
返回一个变量的指针,但是这个指针指向空,你不可以直接对该指针进行操作,否则会报错,除非你将该指针指向一个该类型变量的地址。
make返回一个该类型的变量,以切片变量为例,上面提到,make适用于创建切片、map和channel,但new也可以创建
1 | package main |
输出结果为1
2
3
4
5
6
7
8
9use make create slise type []int value [0 0 0 0 0]
make s1 type []int value [123 0 0 0 321]
use new create slise type *[]int value &[]
new s2 type []int value []
new s2 type *[]int value &[123 0 0 0 3211]
s1 type []int value [123 0 0 0 3211]
m1 use make create type:map[string]string value map[name:yangyanxing age:30]
m2 use new create type:*map[string]string value &map[]
after m2 change m1 value is map[name:fan age:30]
map的初始化
map有以下两种初始化方法
- 使用make函数
- 直接使用map初始化
1 | package main |
slice切片的初始化
同样可以通过make和切片本身进行初始化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package main
import "fmt"
func main() {
//使用make初始化切片,需要传一个len长度,容量cap为可选
//如果不传的话则长度和容量相同
sls1 := make([]int,5,10)
sls1[0] = 100
//append 追加到尾部,这里有点意思
sls1 = append(sls1,200)
// ... 三个点,go里的语法糖,展开前面的切片
sls1 = append(sls1,[]int{30,40}...)
fmt.Println(sls1,len(sls1),cap(sls1))
//out: [100 0 0 0 0 200 30 40] 8 10
sls1 = append(sls1,3,4,6)//超过切片原有容量以后将会发生扩容
fmt.Println(sls1,len(sls1),cap(sls1))
//out: [100 0 0 0 0 200 30 40 3 4 6] 11 20
sls2 := make([]int,3)
sls2[1] = 123
fmt.Println(sls2,len(sls2),cap(sls2))
//out: [0 123 0] 3 3
//直接初始化
sls3 := []int{}
sls3 = append(sls3,10,20)
fmt.Println(sls3,len(sls3),cap(sls3))
//out: [10 20] 2 2
sls4 := []int{1,2,3}
sls5 :=[]int{
1,
2,
5,//这里的逗号不能省
}
fmt.Println(sls4,sls5)
//out: [1 2 3] [1 2 5]
//使用new创建切片,和map一样,返回的也是指针,不能直接对其进行操作
//需要先指向一个变量的地址
sls6 := new([]int)
fmt.Println(sls6)//out: &[]
sls6 = &sls4
fmt.Println(sls6) //out: &[1 2 3]
}
array数组的初始化
数组不能使用make初始化,但是可以使用new初始化
1 | package main |
struct结构体的初始化
结构体不能使用make
,需要使用new
和结构体本身
1 | package main |
欢迎关注我的公众号--序语程言,里面会分享一些编程的基础与一些问题的解决
