
前言
Go语言中,make()和new()的区别与作用?
✅ 一句话总结区别
new:只分配内存,返回指针,不初始化 → 零值对象
make:分配 + 初始化,返回"可用的"引用类型对象 → slice/map/channel 才能用 make
make 的作用
✅ make 只能用于以下 3 种类型:
- slice(切片)
- map(字典/哈希表)
- channel(通道)
这三种类型都属于 引用类型 ,需要底层结构的初始化,因此必须用 make 构造它们的内部数据结构。
📌 1. slice
go
s := make([]int, 5) // 长度 5,容量 5
s2 := make([]int, 0, 10) // 长度 0,容量 10
📌 2. map
go
m := make(map[string]int) // 空 map
m2 := make(map[string]int, 10) // 预分配 bucket
注意:未初始化的 map 是 nil ,不能直接赋值。
📌 3. channel
go
ch := make(chan int) // 无缓冲通道
ch2 := make(chan int, 5) // 带缓冲通道
🚫 make 不能用来创建:
✔ 数组(array)
✔ 结构体(struct)
✔ 指针(pointer)
✔ 接口(interface)
✔ 函数(func)
这些类型要用:
- 字面量(
[]T{},map[K]V{}) - 或
new(T) - 或直接
var x T
🎯 一句话记住:
make只做三件事:初始化 slice、map、channel 的内部数据结构。
✅ new 的作用(基础类型通用)
✔ 功能:
- 分配内存
- 返回一个指向零值的指针(如
*int、*T) - 不初始化内部结构
✔ 适用:
- 任意类型(int、struct、array、map、slice... 都能用 new,但不一定有用)
✔ 示例:
go
i := new(int)
fmt.Println(*i) // 0(零值)
type User struct {
Name string
}
u := new(User)
fmt.Println(u.Name) // "" 零值
❌ 但 new 出来的 slice/map/channel 是不能直接用的!(重要)
go
m := new(map[string]int)
(*m)["a"] = 1 // ❌ panic: assignment to entry in nil map
为什么?因为 map 需要"内部结构",new 并没有初始化它。
⭐ 最重要对比(核心知识点)
| 功能 | make | new |
|---|---|---|
| 用于类型 | slice / map / channel | 所有类型 |
| 返回类型 | 引用类型本身(如 []int, map[...]...) |
指针(如 *int, *User) |
| 是否初始化内部结构 | ✔ 是 | ✘ 否 |
| 是否能直接使用 | ✔ 是 | ❌ 通常不能 |
| 是否用于构造对象 | 部分引用类型 | 任意类型,但仅分配零值 |
⭐ 典型示例:slice / map 的 make vs new
❌ new 创建不可用 map
go
m := new(map[string]int)
(*m)["hello"] = 1 // panic:nil map
✔ make 创建可用 map
go
m := make(map[string]int)
m["hello"] = 1 // OK
❌ new 创建的 slice 也不可直接 append
go
s := new([]int)
*s = append(*s, 1) // panic: nil slice
✔ make 创建 slice 可直接使用
go
s := make([]int, 0, 5)
s = append(s, 1)
fmt.Println(s) // [1]