持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
前言
在学习GO语言中,有两个常用内存分配的关键字:new和make,它们都可以用来为变量分配内容。在一些面试题上也会问到它们有什么区别,那么下面就来学习一下。
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
即参数为一个类型,并返回对应的类型指针,同时会将返回的类型设为零值。
下面创建一个int类型的指针,并使用new分配内存
var i *int
i = new(int)
fmt.Println(*i)
// 0
可以看到输出的值就是int类型的零值0,下面用个结构体来测试一下。
type User struct {
Name string
Age int32
}
func (u User) String() string {
return "name=" + u.Name + ",age=" + fmt.Sprintf("%d", u.Age)
}
func testNew() {
user := new(User)
user.Age = 18
user.Name = "Tom"
fmt.Println(user)
// name=Tom,age=18
}
可以看到运行正常,但平常new关键字使用并不多,通常我们使用var关键字或者结构体字面量来实现变量的声明。
make关键字
make关键字用于map、slice、chan这三个类型的内存分配,并返回对应的引用类型。
// make方法原型
make(type, len, cap)
默认是具有三个参数
type:type的值只能是slice、map、chan这三种数据类型。len:数据类型实际占用的内存空间长度,map、channel是可选参数,slice是必要参数。cap:为数据类型提前预留的内存空间长度,用于slice类型。
使用例子如下
func testMake() {
stringMap := make(map[string]string) // 创建map
ints := make([]int, 1, 2) // 创建int类型切片,长度为1,容量为2
ch1 := make(chan int) // 创建无缓冲int类型通道
ch2 := make(chan int,2)// 创建缓存长度为2的int类型通道
}
那如果我们使用new关键字来创建slice会怎么样呢?
func testNew() {
ints := new([]int)
(*ints)[0] = 1
}
// panic: runtime error: index out of range [0] with length 0
可以看到出现运行时错误:说切片长度为0,这是由于new关键字只会将类型设为零值。因此平常的开发中对于内置容器类型都是使用make关键字的。
两者区别
- make在平常的开发中是经常用到的,而new通常我们并没有使用到
- make返回的是slice、map、chan其中一个引用类型,而new则可以返回任意类型的指针
- new关键字并不适合用于创建slice、map等内置容器