传指针后变量未变,是因为只修改了指针副本的指向(如 p = &another),未解引用赋值(p = 5);Go 中所有参数均为值传递,包括指针,故需通过 p 修改原内存,改指针本身则需 **int。

为什么传指针进去,变量还是没变?
常见错误是只对指针做赋值操作,没解引用修改目标值。比如写 *p = 5 是改原变量,而 p = &another 只是让形参指针指向别处,不影响调用方的指针变量本身(除非你传的是 **int)。
Go 中函数参数永远是值传递——包括指针。传进来的指针变量是原指针的副本,但它存的地址是一样的,所以通过 *p 能改到原始内存位置。
- 要修改外部变量的值:必须用
*p = ... - 要让外部指针变量指向新地址:必须传
*int的地址,即**int,再用*p = &newVal - 如果传的是
nil指针,解引用会 panic,使用前务必检查
修改结构体字段时,该传 *MyStruct 还是 MyStruct?
传 *MyStruct 才能真正修改调用方结构体实例的字段;传值会复制整个结构体,函数内改的是副本,外部无感知。尤其当结构体较大或含 slice/map/channel 时,传指针还能避免不必要的内存拷贝。
注意:即使结构体里字段是 map 或 slice,传值后你仍能往里面增删元素(因为底层引用没变),但无法替换整个字段(如 s.MapField = make(map[string]int) 不会影响外部)。
立即学习“go语言免费学习笔记(深入)”;
- 需要修改字段值、新增/删除字段、或结构体较大 → 用
*MyStruct - 只读访问且结构体很小(如两个 int)→ 值传递也行,更清晰
- 方法接收者用指针(
func (s *MyStruct) Update())才能改字段
nil 指针解引用 panic 怎么安全处理?
函数接收指针参数时,不能默认它非空。典型场景如可选配置、数据库查询结果、JSON 解析后的嵌套字段。直接 *p 会触发 panic: runtime error: invalid memory address or nil pointer dereference。
正确做法是在函数入口显式判断,按需返回错误或设默认值:
func updateName(p *string) error {
if p == nil {
return fmt.Errorf("name pointer is nil")
}
*p = "updated"
return nil
}
- 不要依赖 caller 保证非 nil —— 接口契约应明确是否允许 nil
- 如果业务逻辑允许“不更新”,可用指针判空后跳过赋值,而非报错
- 用
go vet可检测部分未判空的解引用,但不覆盖所有路径
切片传参时,为什么改 slice[i] 生效,但 append 却无效?
切片本身是三元组(底层数组指针 + 长度 + 容量),传值时复制这三元组。因此 slice[i] = x 实际改的是共享的底层数组,外部可见;但 append 可能导致扩容,生成新底层数组,此时新切片只在函数内有效。
若需让外部切片长度/容量同步变化,必须返回新切片并由调用方重新赋值:
func addOne(s []int, v int) []int {
return append(s, v)
}
// 调用方必须写:mySlice = addOne(mySlice, 42)
- 想避免返回重赋值?传
*[]int,再用*s = append(*s, v) - 但多数情况推荐返回新切片——更符合 Go 的惯用法,也避免隐式副作用
- 小切片且确定不扩容时,
append后长度变化对外不可见,容易误判


















