make用于初始化slice、map、channel并返回其本身,new用于分配任意类型内存并返回指向零值的指针;二者适用类型、返回值类型及初始化行为均不同。

Go 内建函数不是语法糖,而是类型系统与运行时契约的直接体现;想靠“背函数列表”学 Go,会卡在 make 和 new 的区别上很久。
为什么 len 对 slice 和 array 返回值一样但行为完全不同
len 看起来简单,但背后是 Go 类型系统的分水岭:它对 []int 返回当前元素个数,对 [3]int 返回固定长度 3 —— 这不是巧合,而是编译期已知 vs 运行期可变的根本差异。误把 slice 当 array 用,比如写 arr := make([]int, 0, 10); arr[0] = 1,会 panic: index out of range,因为 len(arr) 是 0,cap(arr) 才是 10。
- 数组长度是类型的一部分:
[5]int和[6]int是完全不同的类型,赋值必须严格匹配 - slice 的
len可变,但永远 ≤cap;扩容靠append,不是靠改len - 字符串的
len返回字节数,不是 rune 数;要遍历字符得用for range,不是for i := 0; i
make 和 new 永远不能互换,连错误提示都不帮你
new 只做一件事:分配零值内存,返回指针;make 只用于 slice、map、chan,返回的是值本身(非指针)。写 new([]int) 编译通过,但得到的是 *[]int —— 一个指向 nil slice 的指针,后续调用 append 会 panic;而 make([]int, 0) 直接给你一个可用的空 slice。
-
new(T)→*T,T 可以是任意类型,返回的指针指向全零内存 -
make(T, args)→T,T 只能是slice、map、chan,且参数含义不同:make([]int, 5)是 len=5/cap=5,make([]int, 5, 10)是 len=5/cap=10 - map 必须用
make初始化,var m map[string]int声明后是 nil,m["k"] = 1会 panic
别在 panic/recover 里埋逻辑,它们不是 try-catch
panic 是终止当前 goroutine 的信号,recover 只能在 defer 中生效,且仅对同 goroutine 的 panic 有效。把它当错误处理用,比如在 HTTP handler 里 recover 网络错误,会导致连接未关闭、资源泄漏、状态不一致 —— 因为 recover 后程序继续执行,但底层连接可能已断。
-
panic应只用于真正不可恢复的编程错误(如 nil pointer dereference、越界访问),不是业务异常 -
recover的典型场景只有两个:顶层 goroutine 的兜底日志(如 http.Server 的 Serve)、测试中模拟崩溃 - 业务错误必须用多值返回 +
error类型传递,os.Open返回(*File, error)是范式,不是特例
函数签名里带命名返回值,不是为了省打字
写 func parse(s string) (n int, err error) 不只是为了少写 return n, err,而是让函数体内部可以提前 return 而无需重复声明变量。更重要的是,命名返回值会自动初始化为零值 —— n 初始就是 0,err 初始就是 nil,你只需在出错路径上赋值 err = fmt.Errorf(...),成功路径甚至不用碰 n。
- 命名返回值让函数逻辑更聚焦于“什么错了”,而不是“怎么构造返回值”
- 慎用多个命名返回值混用,比如
(ok bool, val T, err error)容易让调用方忽略ok直接用val,应优先用val, ok := m[key]这类 Go 惯用法 - 如果函数有复杂中间状态,命名返回值反而增加理解成本;简单函数(如转换、校验)才最受益
内建函数的边界很硬:它们不抽象、不封装、不隐藏实现细节。学 Go 函数,本质是学 Go 如何用最少的原语表达内存、类型和并发意图 —— make 透露 slice 的三元组结构,len 暴露类型是否定长,recover 揭示 goroutine 隔离模型。绕开这些去记“用法”,就像背菜谱却不懂火候。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











