在 Golang 中,make
和 new
都是用于分配内存的内建函数,但它们的使用场景、返回结果、适用类型和底层行为都截然不同。这个概念经常让初学者混淆。
🔍 一、基本定义
函数 | 用途 | 返回值 | 适用类型 | 是否初始化 | 使用场景 |
---|---|---|---|---|---|
new(T) | 分配内存 | 返回 *T 指针 | 所有类型 | ✅ 置零初始化(Zero Value) | 原始类型或结构体分配 |
make(T) | 创建并初始化内置类型 | 返回 T (非指针) | 仅限 slice、map、chan | ✅ 初始化完成可直接使用 | 通常用于切片、字典、通道 |
🧠 二、详细解析
1. new(T)
—— 分配内存并返回指针
func main() { p := new(int) // *int fmt.Println(*p) // 0(默认值) *p = 42 fmt.Println(*p) // 42 }
-
new(int)
分配了一个int
类型的内存并返回*int
。 -
所有基本类型(int、bool、float、struct)都能用
new
。 -
实质上是:
var x int return &x
✅ 优点:
-
用于分配结构体、基本类型等的指针。
-
会自动置为默认零值(如 0、""、false、nil)。
2. make(T)
—— 初始化切片、map、chan
func main() { s := make([]int, 5) // 创建长度为5的slice m := make(map[string]int) // 创建map c := make(chan int) // 创建channel fmt.Println(s) // [0 0 0 0 0] fmt.Println(m) // map[] }
-
只能用于:✅
slice
,✅map
,✅chan
。 -
返回的是值本身,不是指针!
-
目的是初始化这些引用类型,使其处于“可用状态”。
✅ 示例说明:
// make 是必须的,不然下面会 panic: var m map[string]int m["a"] = 1 // ❌ panic: assignment to entry in nil map m2 := make(map[string]int) m2["a"] = 1 // ✅ ok
🧪 三、例子对比演示
结构体
type Person struct { Name string } func main() { p1 := new(Person) // *Person p2 := &Person{} // 等价于 new(Person) fmt.Println(p1.Name) // "" p1.Name = "李雷" }
🚫 make
不适用于结构体:
// make(Person) // ❌ 编译错误,结构体不能用 make
切片(slice)
s1 := new([]int) // *([]int),值为 nil 的切片指针 s2 := make([]int, 3) // []int,已初始化的切片 fmt.Println(s1) // &[] fmt.Println(*s1) // nil fmt.Println(s2) // [0 0 0]
❗
new([]int)
返回一个切片指针,但里面是 nil,不能直接用;要用make
来初始化容量。
map(字典)
m1 := new(map[string]int) // *map,值为 nil map m2 := make(map[string]int) // 初始化好的 map (*m1)["a"] = 1 // ❌ panic: assignment to entry in nil map m2["a"] = 1 // ✅ ok
channel
c1 := new(chan int) // *chan,值是 nil c2 := make(chan int) // 已初始化的 channel,可用 go func() { c2 <- 42 }() fmt.Println(<-c2) // ✅ ok <-*c1 // ❌ deadlock,因为 c1 是 nil channel
💡 四、何时用 make
,何时用 new
使用目标 | 推荐用法 |
---|---|
创建结构体、int、float、bool等 | ✅ new(T) 或 &T{} |
创建 slice、map、channel | ✅ make(T, ...) |
想要指针 | ✅ new(T) |
想要直接用值 | ✅ make(...) (针对 slice、map、chan) |
🧰 五、图解总结
┌──────────┐ ┌──────────┐ │ new(T) │ │ make(T) │ └──────────┘ └──────────┘ ↓ ↓ ┌────────────────┐ ┌─────────────────────────┐ │ 分配零值内存 │ │ 初始化 slice/map/chan │ │ 返回 *T 指针 │ │ 返回 T 本身 │ └────────────────┘ └─────────────────────────┘
🧠 六、一句话记忆口诀:
new 用于分配内存(返回指针),make 用于初始化三件套(slice、map、chan)!结构体别用 make,slice 别用 new!
👉 立即点击链接,开启你的全栈开发之路:Golang全栈开发完整课程