1.简介
在 Go 语言中,make 和 new 是两个用于创建对象的内建函数,但它们有着不同的用途和适用范围。
make 「只用于」创建(分配内存并初始化) slice、map 和 chan 类型的对象,并返回对象本身。
函数原型:
func make(t Type, size ...IntegerType) Type
使用示例:
// 创建一个初始长度为 5 容量也为 5 的切片
s := make([]int, 5)
// 创建一个初始长度为 0 容量也为 5 的切片
s := make([]int, 0, 5)
// 创建一个映射
m := make(map[string]int)
// 创建一个映射,并给定一个容量提示
m := make(map[string]int, hint)
// 创建无缓冲信道
ch := make(chan int)
// 创建容量为 10 的有缓冲信道
ch := make(chan int, 10)
new 可用于任意类型的分配内存并置为零值,返回指向对象的指针。
函数原型:
// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type
使用示例:
// 创建一个指向 int 类型的零值的指针
p := new(int)
// 创建一个指向结构体类型的零值的指针
type Point struct {
X, Y int
}
p := new(Point)
2.区别
(1)作用不同。
make 既分配内存,也初始化内存,new 只是申请内存,将内存清零,并没有初始化内存。
(2)作用对象不同。
make 只用于 slice、map 以及 channel 的初始化,而 new 可用于任意类型的内存分配。
(3)返回不同。
make 返回的是对象本身,而 new 返回的是指向对象的指针。
new__slicemap__channel__62">3.new 可以初始化 slice,map 和 channel 吗?
不可以。
因为 new 只是申请对应类型的内存并返回指向内存的指针,不做任何初始化操作。
所以我们使用 new 去创建上面几种类型的对象,实际上获得的是对应类型的零值(nil)。
// 先取值,因为 new 返回的是指针。
s := *new([]int)
m := *new(map[int]int)
ch := *new(chan int)
// 等同于
var s []int
var m map[int]int
var ch chan int
对于零值 slice,可以使用 append 追加元素,append 会调用 mallocgc 申请到一块内存,并返回一个新的切片。
对于零值 map,new 没有对 map 做创建桶等初始操作,所以当我们添加键值对的时候会 panic,查询和删除不存在的 key 时不会引发 panic,因为查询和删除都要查找桶和 key,如果没有对应的桶和 key,查询返回零值,删除则不做操作。
对于零值 channel,new 没有对 channel 的缓冲区开辟内存空间以及更多的内部初始化操作,所创建的 channel 始终是 nil,往里面发送或从里面接收数据都会引发 panic。
make__85">4.make 可以初始化其他类型吗?
make 除了创建 slice、map 和 channel,可以初始化其他类型吗,如 int, string?
不可以,编译报错,因为 make 没有对其他类型提供相应的底层方法。
// invalid argument: cannot make int; type must be slice, map, or channel
i := make(int)
5.小结
make 和 new 都是 Golang 的内建函数,都用于创建对象,但是二者有着不同的作用。
总体来说,make 主要用于创建引用类型的数据结构,并进行初始化,而 new 主要用于创建值类型的实例。在实际使用时,根据具体需求选择使用 make 或 new。