必须用解引用指针才能修改原变量:p = newval 修改所指内存值,p = &x 仅改变指针指向;函数内需*p赋值才影响调用方,nil指针解引用会panic。

用 * 解引用指针才能改原变量
Go 里指针本身只是个地址值,不加操作符直接赋值只会改指针变量自己,不会影响它指向的原变量。要改原变量,必须用星号 * 对指针解引用,拿到它指向的内存位置再赋值。
常见错误是写了 p = &newVal(改了指针指向),但实际想改的是 *p = newVal(改指针所指的值)。
-
*p = 42:把p指向的变量值改成42 -
p = &x:让p指向新变量x,和原来指向的变量彻底无关 - 函数参数传指针时,函数内必须用
*param才能修改调用方的原始变量
函数内通过指针参数修改外部变量
这是最典型也最容易出错的场景:函数接收指针参数,但忘了用 * 修改值,导致调用方变量没变。
func increment(p *int) {
*p = *p + 1 // ✅ 正确:解引用后修改原变量
}
func badIncrement(p *int) {
p = new(int) // ❌ 错误:只改了形参 p 的指向,不影响调用方
*p = 100
}
调用 badIncrement(&x) 后,x 的值完全不变;而 increment(&x) 会让 x 真实加 1。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 函数签名里的
*int只表示“我收一个 int 的地址”,不自动触发修改 - Go 没有“引用传递”,所有参数都是值传递——指针参数传递的是地址的副本,所以必须靠
*去操作它指向的内容 - 如果函数不需要修改原变量,就别传指针,避免误解和意外 nil 解引用
nil 指针解引用会 panic
对 nil 指针用 * 是运行时 panic,不是编译错误。很多初学者在函数开头没检查指针是否为 nil,一解引用就崩。
典型错误模式:
func processName(p *string) string {
return *p + " processed" // 如果 p == nil,这里 panic: invalid memory address
}
- 安全做法:先判断
if p == nil,再决定是否解引用 - 结构体字段指针(如
user.Name *string)尤其容易忽略,取值前务必检查 - 使用
fmt.Printf("%v", p)调试时看到<nil></nil>就该警觉
指针和切片、map、channel 的区别
新手常混淆:为什么切片传参不用显式取地址也能“修改原内容”?因为切片本身底层包含指针(指向底层数组),但它的头信息(len/cap/ptr)是值传递。真正需要手动传指针的,是想修改变量本身的值(比如把一个 int 从 5 改成 6),而不是改它“里面的东西”。
-
[]int、map[string]int、chan int这些类型本身就是引用语义类型,函数内追加元素或写入 key,调用方能看到变化 -
*int、*struct{}这类才需要你主动解引用去改那个“变量容器”里存的值 - 混淆这两类,会导致要么多传指针(冗余且易 panic),要么少传(改不生效)
指针真正的复杂点不在语法,而在你得时刻清楚:这个变量是“值本身”,还是“指向值的地址”——稍一走神,* 就该加没加,或者不该加却加了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










