Go语言中new和make关键字的区别详解

蓝鲸
蓝鲸
发布时间:2026-10-15| 3人浏览过
原创

在Go语言开发中,正确区分new和make的使用场景是掌握内存管理的关键。new负责为任意类型分配已清零的内存并返回指针,而make专门用于创建和初始化内置引用类型(slice、map、chan)。理解两者的底层行为能有效避免nil指针解引用和数据结构未初始化的常见Bug。

结果或目标

明确Go语言中new和make两个内置函数的具体职责、返回值类型差异以及适用场景,确保在编写代码时选择正确的内存操作方式。

准备条件

  • 具备基础的Go语言语法知识
  • 了解指针的基本概念
  • 熟悉slice、map和chan这三种基本数据结构

真实操作顺序:深入理解new

第1步:理解new的行为本质

new是Go语言的内置函数,其唯一作用是分配内存。它接收一个类型作为参数,在堆上分配一块足以容纳该类型大小的内存空间,并将这块内存初始化为该类型的零值(例如int为0,string为空字符串),最后返回指向这块内存的地址(即指针)。

核心特征:只分配,不初始化复杂结构;返回类型为*Type。

第2步:查看new的代码签名

从Go源码层面看,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 new
// allocated zero value of that type.
func new(Type) *Type

这表明第一个参数必须是类型而非值,返回值是指向该类型新分配零值的指针。

第3步:通过示例验证new的使用

场景A:基本类型

使用new为int分配内存:

p1 := new(int)
fmt.Printf("p1 --> %#v \n ", p1) // (*int)(0xc42000e250) 
fmt.Printf("p1 point to --> %#v \n ", *p1) // 0

var p2 *int
i := 0
p2 = &i
fmt.Printf("p2 --> %#v \n ", p2) // (*int)(0xc42000e278) 
fmt.Printf("p2 point to --> %#v \n ", *p2) // 0

上述代码证明,new(int)的效果等同于声明一个指针并指向一个初始化为0的值。new分配的内存内容已被清零。

场景B:自定义结构体

type Student struct {
   name string
   age int
}
var s *Student
s = new(Student) //分配空间
s.name = "zhangsan"
fmt.Println(s)

对于自定义类型,new同样只分配内存并将字段设为零值。如果后续直接调用依赖特定初始化逻辑的方法(如slice的append),可能会因为结构未完全初始化而导致panic或逻辑错误,这正是make存在的意义。

真实操作顺序:深入理解make

第1步:理解make的行为本质

make也用于内存分配,但它有严格的适用范围:仅限于slice、map和chan。与new不同,make不仅仅是分配内存,它还初始化了这些类型的内部数据结构(如slice的长度和容量数组指针、map的哈希桶等)。

核心特征:既分配又初始化;返回类型本身就是Type(非指针)。

第2步:查看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. ...
func make(t Type, size ...IntegerType) Type

文档明确指出,对于Slice,size指定长度,可选第二个参数指定容量;对于Map,指定预估元素数量以优化初始分配;对于Channel,指定缓冲容量。

第3步:通过示例验证make的使用

场景:Slice的初始化

var s1 []int
if s1 == nil {
    fmt.Printf("s1 is nil --> %#v \n ", s1) // []int(nil)
}

s2 := make([]int, 3)
if s2 == nil {
    fmt.Printf("s2 is nil --> %#v \n ", s2)
} else {
    fmt.Printf("s2 is not nill --> %#v \n ", s2)// []int{0, 0, 0}
}

这里可以看出,s1声明但未初始化,其值为nil,无法直接使用。s2通过make初始化后,不仅分配了内存,还将长度为3的切片内容填充为int的零值,并返回切片本身。此时可以安全地进行追加等操作。

完成判断:核心差异总结

为了便于记忆和排查问题,以下是new和make的主要区别对照:

  • 适用范围:new可用于任意类型;make仅限slice、map、chan。
  • 返回值类型:new返回指向类型的指针(*Type);make返回类型本身(Type)。
  • 初始化程度:new仅将分配的内存置为零值,不进行复杂初始化;make在分配内存的同时进行必要的内部结构初始化。

简单来说:如果你需要的是一个指向某块内存的指针,用new;如果你需要的是一个已经就绪、可以直接使用的slice/map/channel对象,用make。

简要总结

本文详细解析了Go语言中new和make的区别。new侧重于“分配”,返回指针,适用于所有类型但仅提供零值内存;make侧重于“构建”,返回实例,专用于内置引用类型的完整初始化。在实际开发中,创建slice、map和chan时应始终优先使用make,以避免因结构未初始化导致的运行时错误。

以上就是Go语言中new和make关键字的区别的详细内容,更多关于Go语言内存管理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。