Golang中的nil、new、make的区别与注意事项

nil是go语言中的预先定义的标识符,不是关键字或保留字!

默认值

很多类型的默认值是nil,当然一些基类型的默认值不是nil,这个需要注意,下面是一些初始化值:

布尔类型的零值:false
数值类型的零值:0
字符串类型的零值:空字符串""

除此之外其它类型的默认值为nil,代表下面这些类型的零值:
指针类型(包括unsafe中的)
map类型、slice类型、function类型、channel类型、interface类型

 比如整型和整型指针 :

var n1 *int
​​​​​​​fmt.Printf("%p,%#v\n", n1, n1)
//0x0,(*int)(nil)
 
var n2 int
fmt.Printf("%p,%#v\n", &n2, n2)
//0xc000122078,0

我们可以看到,第一个整型指针的初始指针是nil指针或说无效指针,第二个就是常见的整型,取地址可以看到是正常的有效地址,默认初始化为0

如果我们分别对它们做一个自增的操作,看下会发生什么事情?

var n1 *int
*n1++
fmt.Printf("%p,%#v\n", n1, n1)
/*
	发生异常: panic
	"runtime error: invalid memory address or nil pointer dereference"
*/
 
var n2 int
n2++
fmt.Printf("%p,%#v\n", &n2, n2)
//0xc00001a098,1

第一个就会报错了,因为是nil指针,nil的值,地址方面是无效地址,值不是整形类型的值,所以肯定没法做加法操作,而第二的整型类型当然是没有问题的,可以累加等操作。

不同类型的指针一样

虽然存在各种不同的指针类型,但是初始化的指针都是一样的,如下:

var str *string
fmt.Printf("%p,%#v\n", str, str) //0x0,(*string)(nil)
 
var str1 *[]string
fmt.Printf("%p,%#v", str1, str1) //0x0,(*[]string)(nil)

可以看到他们虽然类型不一样,但是其指针都是0x0,值都是nil

new与make的比较

newmake看起来操作方面是差不多,确实很多时候表面来看也都是没多大区别,比如:

i1 := new(int)
*i1 = *i1 + 3
fmt.Printf("%#v,%#v\n", i1, *i1) //(*int)(0xc0000a6058),3
 
m1 := make(map[string]string)
m1["name"] = "寅恪光潜"
fmt.Printf("%p,%#v\n", m1, m1) //0xc0000b6480,map[string]string{"name":"寅恪光潜"}

都是可以初始化然后进行操作,那为什么会多此一举的要多一个方法呢?其实原理上还是有很大区别,我们来看下这个整型指针的初始化操作:

i := new(*int)
fmt.Printf("%#v,%#v\n", i, *i)
//(**int)(0xc0000c4020),(*int)(nil)

可以看到初始化为nil指针与nil值,这个时候做自增等操作,我们知道那肯定是报错的。

i := new(*int)
**i++
fmt.Printf("%#v,%#v\n", i, *i)
/*
	发生异常: panic
	"runtime error: invalid memory address or nil pointer dereference"
*/

 但是通过make初始化的nil可以将他们初始化成空,地址是有效地址,我们来看下:

m := make(map[string]string)
fmt.Printf("%p,%#v\n", m, m)//0xc000072510,map[string]string{}
 
m["name"] = "寅恪光潜"
fmt.Printf("%p,%#v\n", m, m)//0xc000072510,map[string]string{"name":"寅恪光潜"}

make初始化三种类型

上面我们可以看到make初始化的类型没有出现nil指针以及nil值对吧。
​​​​​​​注意:make只针对mapslicechannel这三个类型做初始化。

Slice := make([]int, 3, 5)
fmt.Printf("%p,%#v,%v,%v\n", Slice, Slice, len(Slice), cap(Slice)) //0xc00000e420,[]int{0, 0, 0},3,5

Map := make(map[string]int, 5)
fmt.Printf("%p,%#v,%v\n", Map, Map, len(Map)) //0xc0000725a0,map[string]int{},0
Map["h1"] = 110
fmt.Printf("%p,%#v,%v\n", Map, Map, len(Map)) //0xc0000725a0,map[string]int{"h1":110},1

Chan := make(chan int, 5)
fmt.Printf("%p,%#v,%v\n", Chan, Chan, len(Chan)) //0xc000102000,(chan int)(0xc000102000),0

你可能感兴趣的:(Golang,map[type][type],slice切片,new与make,nil指针,nil值)