Go new和make的区别

252 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4天,点击查看活动详情

前言

Go的指针类型,必须要先做初始化(即分配内存地址),然后才能正确的做写操作。初始化可以使用new或make,这两个内置函数来完成,但两者之间有所区别,需要注意。

先说结论

区别点

  1. 主要作用不同new 只分配内存,获取指向某个类型的指针 ; make主要作用是初始化内置的数据结构,也就是 slice、map 和 channel 的初始化
  2. 函数返回值不同new返回对应类型的指针;make返回对应类型的本身
  3. 作用范围不同new可作用于任何类型;make只作用于slice、map、channel

new

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

解释说明:new 函数只接受一个参数,这个参数是一个类型,并且返回一个指向该类型内存地址的指针。同时 new 函数会把分配的内存置为零,也就是类型的零值。

使用例子

var num *int
num = new(int)  //使用new初始化,分配内存地址
*num = 100
fmt.Println(num) //0xc00001a098

如果未使用new进行初始化,则会panic:

panic: runtime error: invalid memory address or nil pointer dereference

make

make函数定义

// The make built-in function allocates and initializes an object of type
// slice, map, or chan (only). Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
//  Slice: The size specifies the length. The capacity of the slice is
//  equal to its length. A second integer argument may be provided to
//  specify a different capacity; it must be no smaller than the
//  length. For example, make([]int, 0, 10) allocates an underlying array
//  of size 10 and returns a slice of length 0 and capacity 10 that is
//  backed by this underlying array.
//  Map: An empty map is allocated with enough space to hold the
//  specified number of elements. The size may be omitted, in which case
//  a small starting size is allocated.
//  Channel: The channel's buffer is initialized with the specified
//  buffer capacity. If zero, or the size is omitted, the channel is
//  unbuffered.
func make(t Type, size ...IntegerType) Type

解释说明:参数t只用于 slicemap 以及 chan 的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

另外,在编译期间的类型检查阶段,Go语言其实就将代表 make 关键字的 OMAKE 节点根据参数类型的不同转换成了 OMAKESLICEOMAKEMAPOMAKECHAN三种不同类型的节点,这些节点最终也会调用不同的运行时函数来初始化数据结构。

使用例子

var m map[string]string
m = make(map[string]string) //使用make初始化,分配内存地址
m["name"] = "zhangsan"
fmt.Println(m, fmt.Sprintf("%p", m)) //map[name:zhangsan] 0xc000100030

如果未使用make进行初始化,则会panic:

panic: assignment to entry in nil map

总结

可使用newmake对指针类型进行初始化。new可作用于任何类型,并返回对应类型的指针;make只作用于slice、map和channel,并返回对应类型的本身。

如果本文对你有帮助,欢迎点赞收藏加关注,如果本文有错误的地方,欢迎指出!