在 Go 语言中,new
和 make
都是用于内存分配的内置函数,但它们有不同的用途和行为。初学者在学习 Go 时,往往会对这两个函数感到困惑。本文将详细介绍 new
和 make
的区别,并帮助你理解它们的应用场景。
文章目录
一、new
函数
new
函数用于为类型分配内存,但不初始化内存。它返回的是指向分配类型的指针。使用 new
分配的内存区域会被置为零值(即初始化为默认值,如 int
为 0
,bool
为 false
,指针为 nil
等)。
1.1 语法
p := new(T)
这里的 T
是一个类型,p
是指向类型 T
的指针。new
函数只分配内存,不做初始化工作。因此,new(T)
返回的指针指向类型 T
的零值。
1.2 示例
package main
import "fmt"
func main() {
num := new(int)
fmt.Println(*num) // 输出: 0
}
在这段代码中,new(int)
为 int
类型分配了内存,并返回一个指向该内存的指针。由于 new
函数不会初始化数据,所以 *num
的值是 0
,这是 int
类型的零值。
1.3 使用场景
new
主要用于分配内存,并返回指向分配内存的指针,适用于那些不需要显式初始化的情况。通常在需要创建指向零值对象的指针时使用 new
。
二、make
函数
make
函数用于为引用类型(slice、map 和 channel)分配和初始化内存。make
不是返回指针,而是返回这些引用类型本身。它不仅分配内存,还会对类型进行初始化,以便可以直接使用。
2.1 语法
make(t Type, size ...IntegerType) Type
其中 Type
必须是 slice、map 或 channel,size
取决于类型。例如,slice 需要指定长度,map 可以指定容量,channel 也可以指定容量。
2.2 示例
创建 slice
package main
import "fmt"
func main() {
slice := make([]int, 5)
fmt.Println(slice) // 输出: [0 0 0 0 0]
}
在这段代码中,make([]int, 5)
创建了一个长度为 5 的 int
类型的 slice,并且每个元素都被初始化为 0
。
创建 map
package main
import "fmt"
func main() {
m := make(map[string]int)
m["key"] = 1
fmt.Println(m) // 输出: map[key:1]
}
make(map[string]int)
创建了一个空的 map,之后我们可以向其中添加键值对。
2.3 使用场景
make
用于 slice、map 和 channel 这三种引用类型的内存分配和初始化。通过 make
创建的对象可以直接使用,而不需要进一步初始化。
三、new
和 make
的区别
-
用途不同:
new
用于分配任何类型的内存,返回指针,内存内容为零值;make
用于分配并初始化 slice、map 和 channel 等引用类型,返回的不是指针,而是类型本身。 -
返回值不同:
new
返回指向类型的指针;make
返回 slice、map 或 channel 的引用。 -
适用类型不同:
new
可用于所有类型的内存分配,而make
仅适用于 slice、map 和 channel。
特性 | new | make |
---|---|---|
用途 | 分配内存并返回指针 | 分配并初始化引用类型的内存 |
返回值 | 指向分配内存的指针 | slice、map 或 channel 本身 |
使用场景 | 任何类型(值类型、引用类型) | 仅适用于 slice、map、channel |
四、总结
Go 语言中的 new
和 make
是两种用于内存分配的内置函数,但它们的使用场景和返回结果完全不同。new
用于分配任意类型的内存,返回类型的指针;而 make
则专门用于引用类型的初始化,返回类型本身。
通过本文的详细讲解,相信你已经掌握了 new
和 make
的区别和使用场景。在开发中,理解这些基础概念对编写高效、健壮的 Go 代码至关重要。