go中函数参数传t无法修改原指针变量,因传递的是指针值副本;要改变原指针需用*t或直接返回指针。

函数参数传 *T 时,为什么改不了原指针变量本身
Go 所有参数都是值传递,*T 参数传进去的只是指针值的副本。你可以在函数内通过 *p = v 修改它指向的值,但给 p 重新赋值(比如 p = new(T))只会影响副本,调用方的原始指针变量仍保持不变。
- 常见错误:在函数里写
session, err = mgo.Dial(url),却期望外面的session变成非 nil —— 实际上它还是nil - 真正想“让外部指针变量指向新地址”,必须用
**T:函数接收pp **T,然后写*pp = new(T)或*pp = &x - 更推荐的做法是直接返回指针:
func connect() *Session,而不是靠参数副作用初始化
传指针参数前,必须检查是否为 nil 吗
不是“必须”,但解引用前不检查就 panic。Go 不做空指针防护,*p 在 p == nil 时直接崩溃,且无堆栈上下文提示。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 函数签名若允许
nil(如可选配置、未设置字段),开头加if p == nil { return }或if p == nil { panic("xxx: p must not be nil") } - 结构体字段为指针类型(如
Name *string)时,JSON 反序列化后可能为nil,直接访问u.Name没问题,但*u.Name就会 panic - 接口变量底层是 nil 指针(如
var r io.Reader = (*bytes.Buffer)(nil)),调r.Read()同样 panic
& 只能作用于可寻址变量,哪些地方会编译报错
& 是取地址操作符,只能用于有固定内存位置的具名变量或其可寻址子项。对临时值取地址是编译期错误,不是运行时 panic。
-
&42、&"hello"、&true→ 报错:cannot take the address of 42 -
&m["k"]→ 报错:map value 是拷贝,不是变量;要改值直接写m["k"] = v -
&getValue()→ 除非函数返回的是变量地址(如全局变量或逃逸到堆的局部变量),否则非法 -
&s[i](s是切片)→i超界时编译不报错,但运行时 panic;i合法时才真正可寻址
数组指针 *[N]T 和切片 []T 完全不能混用
*[3]int 是一个独立类型,表示“指向长度为 3 的 int 数组”的指针,N 是类型的一部分,不可省略、不可隐式转换。
-
arr := [3]int{1,2,3}; p := &arr→p类型是*[3]int,不是*[]int,也不能赋给*[5]int -
json.Unmarshal(data, &arr)合法;但json.Unmarshal(data, &slice)编译失败,因为&slice是*[]int,类型不匹配 - 想把
*[3]int当切片用?得显式转:(*p)[:],否则传不进接受[]int的函数 - 大定长数组(如
[1024]byte)才值得用*[N]T避免拷贝;小数组传值更轻量
*T 就能“控制外部变量”,其实只能控制它指向的值;而真正想改变指针本身,要么用 **T,要么换回返回值方式——后者更清晰、更符合 Go 习惯。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










