必须用make而不能用new:make是唯一能安全创建可读写slice、map、chan的方式,因其完成底层状态初始化(如len/cap、哈希桶、缓冲区),而new仅分配零值内存并返回nil指针,解引用后操作必panic。

别用 new 初始化 []int、map[string]int 或 chan int——它只会给你一个不可用的 nil 值,后续操作直接 panic。
什么时候必须用 make 而不能用 new
make 是唯一能安全创建可读写 slice、map、chan 的方式。这三个类型底层有状态(比如 slice 的 len/cap、map 的哈希桶、chan 的缓冲区),new 只分配零值内存,不初始化这些状态。
-
new([]int)返回*[]int,解引用后仍是nil切片,append或下标赋值会 panic -
new(map[string]int)返回*map[string]int,解引用后是nil map,assignment to entry in nil map报错 -
new(chan int)返回*chan int,解引用后是nil chan,send/receive永远阻塞或 panic - 结构体字段含
slice/map/chan时,new(Struct)不初始化这些字段,它们仍是nil,需单独make
make 的参数怎么传才不踩坑
make 的参数含义因类型而异,传错会导致容量误判或行为不符合预期。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
-
slice:签名是make([]T, len, cap),cap是可选的;省略时等价于cap == len;想预留空间避免扩容,就显式传第三个参数,比如make([]int, 0, 100) -
map:签名是make(map[K]V, hint),hint是预估元素个数(不是硬性容量),Go 会向上取整到 2 的幂,make(map[int]string, 10)实际可能分配 16 个桶 -
chan:签名是make(chan T, buffer),buffer是缓冲区长度;buffer为 0 或省略时是无缓冲 channel
len 和 cap 能查什么、不能查什么
len 和 cap 是编译器内置函数,只接受特定类型,传错类型会编译失败。
- 支持类型:数组、
slice、string、map、chan -
len对slice/array/string返回元素个数;对map返回键值对数量;对chan返回当前队列中元素个数(非缓冲区大小) -
cap对slice返回底层数组剩余可用长度;对array返回数组总长度;对chan返回缓冲区长度;cap对map和string无效,编译报错 - 常见误用:
cap("hello")或len(nil)都不合法,前者编译失败,后者语法错误(nil不是支持类型)
new 真正该用在哪
new 的唯一职责是:分配零值内存并返回指针。它适合需要明确堆上指针、且类型不含内部状态的场景。
- 基础类型:
new(int)、new(string)返回指向零值的指针,安全可解引用 - 结构体:
new(MyStruct)返回*MyStruct,所有字段为零值,但若字段含slice/map/chan,这些字段仍是nil - 和
&MyStruct{}的区别:后者在栈上分配(除非逃逸分析决定移到堆),new明确在堆分配,生命周期更可控 - 不要用它替代构造函数逻辑——比如想初始化带非零字段的结构体,直接用字面量或工厂函数更清晰
最常被忽略的是:即使你记得 make 用于 slice/map/chan,也容易在嵌套结构体里漏掉对内部引用字段的 make 调用,导致运行时 panic。检查每个 nil 操作前,先确认它是否被 make 过。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










