golang new 和 make 的区别
以下通过代码示例对比 new 和 make 的区别,涵盖 结构体、切片、映射、通道 四种场景:
1. 结构体(Struct)
type Person struct {
Name string
Age int
}
// 使用 new 创建结构体指针
p1 := new(Person) // 返回 *Person 类型指针
fmt.Println(p1) // 输出: &{ 0}(字段为零值)
// 使用 make 无效(编译报错)
// p2 := make(Person, 0) // 错误:make 仅用于 slice/map/channel
- 区别:
new返回指向零值的指针,适用于任何类型。make不能用于结构体,会报错。
2. 切片(Slice)
// 使用 new 切片(不推荐)
s1 := new([]int) // 返回 *[]int 类型指针
fmt.Println(s1) // 输出: <nil>(切片未初始化,无法直接使用)
// (*s1) = make([]int, 3) // 需手动分配内存才能使用
// 使用 make 初始化切片
s2 := make([]int, 3) // 返回 []int 类型切片
fmt.Println(s2) // 输出: [0 0 0](元素初始化为零值)
- 区别:
new([]int)返回切片指针,但切片本身是nil,需手动make初始化。make([]int, 3)直接返回可用切片,元素已初始化。
3. 映射(Map)
// 使用 new 映射(不推荐)
m1 := new(map[string]int) // 返回 *map[string]int 指针
fmt.Println(m1) // 输出: <nil>(映射未初始化,无法直接使用)
// (*m1)["key"] = 100 // 运行时错误:panic: assignment to entry in nil map
// 使用 make 初始化映射
m2 := make(map[string]int) // 返回 map[string]int 类型映射
m2["key"] = 100
fmt.Println(m2) // 输出: map[key:100]
- 区别:
new(map[KeyType]ValueType)返回映射指针,但映射本身是nil,需手动初始化。make(map[KeyType]ValueType)直接返回可用映射。
4. 通道(Channel)
// 使用 new 通道(不推荐)
ch1 := new(chan int) // 返回 *chan int 指针
fmt.Println(ch1) // 输出: <nil>(通道未初始化,无法直接使用)
// *ch1 <- 1 // 运行时错误:panic: send on nil channel
// 使用 make 初始化通道
ch2 := make(chan int, 2) // 返回 chan int 类型通道
ch2 <- 1
ch2 <- 2
fmt.Println(<-ch2) // 输出: 1
- 区别:
new(chan T)返回通道指针,但通道本身是nil,需手动初始化。make(chan T, buffer)直接返回可用通道。
总结对比表
| 场景 | new 行为 |
make 行为 |
|---|---|---|
| 结构体 | 返回指向零值的指针(如 *Person) |
无效,编译报错 |
| 切片 | 返回切片指针(*[]int),但切片为 nil,需手动初始化 |
返回初始化后的切片(如 []int{0, 0, 0}) |
| 映射 | 返回映射指针(*map),但映射为 nil,需手动初始化 |
返回初始化后的空映射(如 map[]) |
| 通道 | 返回通道指针(*chan),但通道为 nil,需手动初始化 |
返回初始化后的通道(如带缓冲的 chan int) |
关键区别总结
-
适用类型:
new:适用于 所有类型(如int,struct,slice等)。make:仅适用于 切片、映射、通道。
-
返回值类型:
new(T)返回*T(指针)。make(T, ...)返回T(值类型,非指针)。
-
初始化程度:
new:仅初始化为零值(如nil、0、空字符串)。make:对复杂类型(如切片、映射)进行 完整初始化,使其可直接使用。
浙公网安备 33010602011771号