new仅分配内存并返回指针,对slice/map/chan生成未初始化的“空壳”,直接使用会panic;make专用于这三种类型,完成内存分配与结构初始化,返回可直接使用的值。

new 只分配内存,不初始化复杂结构
用 new 创建 slice、map 或 chan 会得到一个“空壳”:内存分配了,但内部关键字段(如 map 的哈希表、slice 的底层数组指针)仍是 nil。直接使用必然 panic。
-
var m *map[string]int = new(map[string]int→(*m)["k"] = v触发panic: assignment to entry in nil map -
s := new([]int)→*s = append(*s, 1)虽能跑通,但绕路且易错;len(*s)返回 0,cap(*s)也是 0,底层数组未分配 - 适用场景仅限:需要一个指向零值的指针,且后续会手动赋值,比如
p := new(int)然后*p = 42
make 专为 slice/map/chan 设计,一步到位初始化
make 不是通用分配器,它只认三种类型:切片、映射、通道。它做的事远不止分配内存——它把底层结构全配齐,返回可立即使用的值(不是指针)。
-
slice := make([]int, 3)→ 分配长度为 3 的底层数组,len(slice)==3,cap(slice)==3,元素全为 0 -
m := make(map[string]int)→ 初始化哈希桶,可直接m["x"] = 1 -
ch := make(chan int, 10)→ 创建带缓冲区的 channel,发送不会阻塞直到满 - 参数差异明显:
make([]T, len, cap)中cap可选;make(map[T]U, hint)中hint是预估容量,非必须;make(chan T, cap)中cap决定缓冲区大小
返回值类型不同,直接影响赋值和传参方式
new(T) 总是返回 *T;make(T) 返回的类型就是 T 本身(T 必须是 []X、map[X]Y 或 chan X)。这个区别在函数签名和变量声明里非常关键。
- 写
func f(m map[string]int),就得传make(map[string]int)得到的值;传*map[string]int会编译报错 - 写
func g(p *int),就得传new(int);传make([]int, 1)类型不匹配 - 常见误写:
var s []int; s = new([]int)—— 这里new([]int)返回的是*[]int,不能直接赋给[]int
结构体和基本类型只能用 new,不能用 make
make 对类型有硬性限制,遇到 struct、int、string 等直接报错:cannot make type struct {…}。这时候必须用 new 或字面量。
-
type User struct{ ID int; Name string }→u := new(User)合法,u := make(User)编译失败 -
i := new(int)和i := &int(0)等价,但后者更少见;i := make(int)语法错误 - 注意:虽然
new能用于任何类型,但对 slice/map/chan 来说,它只是“半成品”,而make才是“出厂设置”
make 返回的不是指针,却能跨函数修改底层数组或哈希表——这不是因为返回了指针,而是因为这些类型的设计语义如此。混淆这点,就容易写出看似正确、实则低效或出错的代码。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











