官方定义:new是一个分配内存的内置函数,第一个参数是类型,而不是值,返回的值是指向该类型新分配的零值的指针。
func new(Type) *Type
我们平常在使用指针的时候是需要分配内存空间的,未分配内存空间的指针直接使用会使程序崩溃,比如这样:
var a *int64
*a = 10
我们声明了一个指针变量,直接就去使用它,就会使用程序触发panic,因为现在这个指针变量a在内存中没有块地址属于它,就无法直接使用该指针变量,所以new函数的作用就出现了,通过new来分配一下内存,就没有问题了:
var a *int64 = new(int64)
*a = 10
上面的例子,我们是针对普通类型int64进行new处理的,如果是复合类型,使用new会是什么样呢?来看一个示例:
func main() { // 数组 array := new([5]int64) fmt.Printf("array: %p %#v \n", &array, array) // array: 0xc0000ae018 &[5]int64{0, 0, 0, 0, 0} (*array)[0] = 1 fmt.Printf("array: %p %#v \n", &array, array) // array: 0xc0000ae018 &[5]int64{1, 0, 0, 0, 0} // 切片 slice := new([]int64) fmt.Printf("slice: %p %#v \n", &slice, slice) // slice: 0xc0000ae028 &[]int64(nil) (*slice)[0] = 1 fmt.Printf("slice: %p %#v \n", &slice, slice) // panic: runtime error: index out of range [0] with length 0 // map map1 := new(map[string]string) fmt.Printf("map1: %p %#v \n", &map1, map1) // map1: 0xc00000e038 &map[string]string(nil) (*map1)["key"] = "value" fmt.Printf("map1: %p %#v \n", &map1, map1) // panic: assignment to entry in nil map // channel channel := new(chan string) fmt.Printf("channel: %p %#v \n", &channel, channel) // channel: 0xc0000ae028 (*chan string)(0xc0000ae030) channel <- "123"// Invalid operation: channel <- "123" (send to non-chan type *chan string)
}
从运行结果可以看出,我们使用new函数分配内存后,只有数组在初始化后可以直接使用,slice、map、chan初始化后还是不能使用,会触发panic,这是因为slice、map、chan基本数据结构是一个struct,也就是说他里面的成员变量仍未进行初始化,所以他们初始化要使用make来进行,make会初始化他们的内部结构,我们下面一节细说。还是回到struct初始化的问题上,先看一个例子:
type test struct { A *int64
}
func main() { t := new(test) *t.A = 10 // panic: runtime error: invalid memory address or nil pointer dereference // [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x10a89fd] fmt.Println(t.A)
}
从运行结果得出使用new()函数初始化结构体时,我们只是初始化了struct这个类型的,而它的成员变量是没有初始化的,所以初始化结构体不建议使用new函数,使用键值对进行初始化效果更佳。
其实** new 函数在日常