在 Go 语言中,new 和 make 是两个用于内存分配的内置函数,但它们有不同的用途和行为。理解它们之间的区别对于正确地使用 Go 语言的内存管理至关重要。
new 和 make 的区别
- new 函数:
用途:new 用于为变量分配内存,并返回指向该内存的指针。
返回值:new 返回的是一个指向类型的指针,且该内存区域会被初始化为零值(例如整数为 0,布尔为 false,指针为 nil)。
适用类型:可以用于所有类型,包括基本类型(如 int、float 等)和复合类型(如 struct、数组等)。
语法:new(T),其中 T 是要分配的类型。
- make 函数:
用途:make 用于为特定类型的数据结构分配和初始化内存,这些类型包括切片(slice)、映射(map)和信道(channel)。
返回值:make 返回初始化后的值,而不是指针。
适用类型:只能用于切片、映射和信道,不能用于其他类型。
语法:make(T, size),其中 T 是要分配的类型,size 是指定的大小(对于映射和信道是容量)。
代码实例
使用 new
package main
import "fmt"
func main() {
// 使用 new 分配一个 int 类型的指针
ptr := new(int)
fmt.Println(ptr) // 输出指针地址,例如:0xc000016088
fmt.Println(*ptr) // 输出零值:0
// 将指针指向的值修改为 100
*ptr = 100
fmt.Println(*ptr) // 输出:100
// 使用 new 分配一个 struct 的指针
type Person struct {
Name string
Age int
}
p := new(Person)
fmt.Println(p) // 输出:&{ 0},零值初始化
fmt.Println(p.Name) // 输出:""(空字符串)
fmt.Println(p.Age) // 输出:0
// 修改结构体中的字段
p.Name = "Alice"
p.Age = 30
fmt.Println(*p) // 输出:{Alice 30}
}
使用 make
package main
import "fmt"
func main() {
// 使用 make 分配一个切片
slice := make([]int, 5) // 创建一个长度为 5 的切片,初始值为 0
fmt.Println(slice) // 输出:[0 0 0 0 0]
slice[0] = 10
fmt.Println(slice) // 输出:[10 0 0 0 0]
// 使用 make 分配一个映射
myMap := make(map[string]int)
myMap["key1"] = 100
fmt.Println(myMap) // 输出:map[key1:100]
// 使用 make 分配一个信道
ch := make(chan int, 2) // 创建一个容量为 2 的缓冲信道
ch <- 1
ch <- 2
fmt.Println(<-ch) // 输出:1
fmt.Println(<-ch) // 输出:2
}
总结
- new:用于分配内存并返回指针。适用于所有类型。分配的内存会被初始化为类型的零值。
- make:用于初始化切片、映射和信道,返回的是初始化后的类型,而不是指针。make 不会返回指针,因为它返回的是已经初始化好的数据结构。
正确理解和使用 new 和 make,可以更好地管理 Go 语言中的内存分配和数据结构初始化。