new(T)
会为类型T
分配内存,并返回一个指向该类型的指针,该指针指向的内存被初始化为类型T
的零值。
这里关键是要理解分配零值填充的值的含义,像数值和字符创这种基本类型,使用new实例化后得到的是一个指针类型,而且使用零值进行填充。
实际上只要是使用new或者make进行实例化就一定分配了内存,因此得到的变量就不可能是nil了。
比如:
i := new(int)
fmt.Println(*i)
s1 := new(string)
fmt.Println(*s1)
这里变量i和s1并不是nil,而会被填充零值,也就是会得到一个值为0的指针类型的i和值为空字符串的指针类型的s1.
但如果是slice,map,channel这些容器类型
是如果使用make初始化,比如
s := make([]int, 5)
这里切片s不仅申请了5个存放int的空间,而且每个元素都会被填充0值,也就是会得到一个拥有5个元素的切片,只不过元素的值为0
但是如果使用new来实例化,会得到一个指针类型的切片,这个指针切片指向了一个空切片,这个切片没有任何元素,但需要注意的是,这个指针类型的切片本身虽然不是nil,但它的值指向了nil。
s2 := new([]int)
所以对于s2来说,虽然这个指针类型不是nil,但是它的指向的值会被填充零值,也就是*s2是等于nil的。
因此也特别需要留意map,slice这种类型
比如map类型,如果它的值是nil是无法直接使用的,如果直接增加元素就会抛出panic
m1 := new(map[int]int)
fmt.Println(*m1 == nil)
(*m1)[1] = 1
比如上面这个例子,给*m1增加元素的时候就会panic