必须用 *T 而不是 T 才能修改调用方的指针变量本身(如重定向或置 nil);*T 只能修改其指向的值,因 Go 参数均为值传递。
**T 而不是 *T
只有当你需要在函数内部**修改调用方持有的指针变量本身**(比如让它指向新地址、置为 nil),才真正需要 **T。传 *T 只能改它指向的值,改不了指针自己——因为 Go 里所有参数都是值传递。
func setToFive(p *int) { p = &five } → 外部 ptr 不变func setToFive(pp **int) { *pp = &five } → 传 &ptr,*pp 就是原 ptr 变量C.get_string(&cPtr))***T 是否合法?为什么几乎不用***T 在语法上完全合法,Go 类型系统允许任意嵌套,但它不是“多级指针语法糖”,而是明确指向一个 **T 变量的地址。实际项目中极少出现,一旦看到,大概率说明设计可以简化。
*:若 ppp 是 ***int,取值必须写 ***ppp,少一次类型错,多一次 panicif ppp != nil && *ppp != nil && **ppp != nil 才敢访问
type IntRef struct { Ptr **int })、返回新指针、或用 sync/atomic.Value 安全替换**T 的硬性操作步骤任何对 **T 的解引用都必须前置非空校验,Go 不做隐式防护,nil 解引用直接 panic。
var pp **int → *pp 会 panicval := 42 p := &val // *int pp := &p // **int
if pp != nil && *pp != nil { use **pp },顺序不可颠倒(&& 短路)运行时报 panic: runtime error: invalid memory address or nil pointer dereference 是多级指针最常触发的错误,根源几乎总是某一层未初始化或提前被置 nil。
var pp **int; *pp = &x → pp 是 nil,*pp 就非法fmt.Printf("pp=%v, *pp=%v\n", pp, *pp),快速定位哪一层断了cPtr 保持 nil),Go 层必须先检查再解引用**T 拆成“返回新指针 + 显式赋值”或封装进方法,代码反而更直白、更易测、更少出错。