商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Go语言中 make 和 new 的区别是什么

Go语言中 make 和 new 的区别是什么

  发布于2026-07-12 阅读(0)

扫一扫,手机访问

先说一个核心判断:makenew 可不是随便换着用的。用错了,轻则 panic,重则运行时 nil 指针解引用。这根本不是风格差异,而是 Go 类型系统给你划下的硬杠杠。

哪些类型只能用 make?

简单来说,make 是专门给 slicemapchan 这三个“亲儿子”用的。其他任何类型,比如 struct[]int 的指针、*map[string]int,你传给 make,编译器直接翻脸,编译失败。

  • make([]int, 5) ✅ 返回一个长度为 5、元素全为 0 的切片值,直接可用
  • make(map[string]int) ✅ 返回一个可直接 m["k"] = 1 赋值的 map 值
  • make(chan int, 10) ✅ 返回带缓冲区的 channel 值
  • make(struct{X int}) ❌ 编译错误:cannot make type struct { X int }
  • make(*[]int) ❌ 编译错误:cannot make type *[]int

new 返回指针,make 返回值本身

这是两者最本质的区别。new(T) 永远返回 *T,一个指向 T 类型零值的指针;而 make(T, ...),只认那三种类型,返回的是 T 类型的值(不是指针),并且已经初始化好,拿过来就能用。

  • p := new(int)p*int*p == 0
  • s := make([]int, 3)s[]intlen(s) == 3,可直接 s[0] = 1
  • m := new(map[string]int) ❌ 不合法:虽然语法上 new 允许,但它返回的是 *map[string]int,一个指向 nil map 的指针。解引用后 *m 仍然是 nil,后续 (*m)["k"] = 1 必然 panic。

误用 new 初始化 map/slice/chan 的典型崩溃场景

很多新手会写 var m = new(map[string]int)m := new(map[string]int),看着合法,但实际拿到的只是一个指向 nil map 的指针。结果就是,解引用后,你面对的还是 nil,啥也干不了。

  • m := new(map[string]int)m 类型是 *map[string]int*m == nil
  • (*m)["x"] = 1 → panic: assignment to entry in nil map
  • 正确做法只有两种:要么 m := make(map[string]int)(要值),要么 m := &map[string]int{}(先 make 再取地址,实际很少用)
  • 同理,s := new([]int) 得到的是 *[]int*s == nil,对 *s 调用 append 也会 panic。

结构体和自定义类型该用哪个?

对于结构体,make 肯定不行,new 也不是最佳选择。优先用字面量;需要指针时,&MyStruct{}new(MyStruct) 更直观,而且还能顺手设置初始字段值。

  • s := MyStruct{Name: "a"} → 值类型,栈上分配可达
  • s := &MyStruct{Name: "a"} → 指针,等价于 new(MyStruct) + 字段赋值,但写法更清晰
  • new(MyStruct) → 所有字段都是零值,无法指定初始值,语义弱了一截
  • make(MyStruct) → 编译报错:cannot make type MyStruct

一个容易被忽略的细节是:你写的变量是否「需要被外部修改」,或者内部是否「含有需要初始化的引用字段」——到这时候,通常得自己写 NewXXX() 函数,而不是依赖 newmake 来解决。

本文转载于:https://www.php.cn/faq/2376105.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注