抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

前言

在学习GO语言中,有两个常用内存分配的关键字:new和make,它们都可以用来为变量分配内容。在一些面试题上也会问到它们有什么区别,那么下面就来学习一下。

new关键字

先来看下官方对于new关键字的定义

1
2
3
4
// 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分配内存

1
2
3
4
var i *int
i = new(int)
fmt.Println(*i)
// 0

可以看到输出的值就是int类型的零值0,下面用个结构体来测试一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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关键字用于mapslicechan这三个类型的内存分配,并返回对应的引用类型。

1
2
// make方法原型
make(type, len, cap)

默认是具有三个参数

  • typetype 的值只能是 slicemapchan 这三种数据类型。
  • len:数据类型实际占用的内存空间长度,mapchannel 是可选参数,slice 是必要参数。
  • cap:为数据类型提前预留的内存空间长度,用于slice类型。

使用例子如下

1
2
3
4
5
6
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会怎么样呢?

1
2
3
4
5
func testNew() {
ints := new([]int)
(*ints)[0] = 1
}
// panic: runtime error: index out of range [0] with length 0

可以看到出现运行时错误:说切片长度为0,这是由于new关键字只会将类型设为零值。因此平常的开发中对于内置容器类型都是使用make关键字的。

两者区别

  1. make在平常的开发中是经常用到的,而new通常我们并没有使用到
  2. make返回的是slice、map、chan其中一个引用类型,而new则可以返回任意类型的指针
  3. new关键字并不适合用于创建slice、map等内置容器