最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Go 中函数参数传递方式:值传递本质与指针传递的适用场景
时间:2026-07-13 09:08:52 编辑:袖梨 来源:一聚教程网
<p>Go函数参数永远是值传递,传指针实为传地址值,修改解引用后内存才影响原变量;大结构体、需修改原值或方法写字段时才必须用* T;slice/map/channel的可变性源于内部指针,非引用传递。</p>
Go 函数参数永远是值传递,不存在引用传递;所谓“指针能改原值”,是因为你传的是地址这个值,解引用后操作的是同一块内存。
func f(x T) 的 x 永远是副本
不管 T 是 int、string 还是 struct{},x 都是调用时传入值的一份拷贝。修改 x 不会影响调用方的原始变量。
- 传
int:副本里存的是数字(比如42),改它只是改副本 - 传
*int:副本里存的是地址(比如0xc00001a080),*x = 100写的是该地址指向的内存 - 传
[]byte或map[string]int:它们底层是含指针的结构体,所以副本仍指向同一底层数组或哈希表——但这仍是值传递,只是“值”里带指针
什么时候必须用 *T 而不是 T
不是“想改就用指针”,而是不传指针就完不成目标时才必须用。
- 需要修改调用方的原始变量:比如
swap(a, b *int)或json.Unmarshal(data []byte, v interface{})要求v是指针 - 结构体很大(字段多、含大 slice/map、或数组长度大):避免复制开销,例如
type Config struct { Data [1e6]byte },传Config会拷贝 1MB - 方法接收者需写字段:如
func (u *User) SetName(n string) { u.Name = n },值接收者(u User)改了也白改
常见 panic 和误判点
传 nil 指针进函数再解引用,会直接 panic: runtime error: invalid memory address or nil pointer dereference。
- 传
nil *User然后执行u.Name = "x"→ panic - 但传
User{}(零值)是安全的,哪怕字段是空 slice 或 map - 别以为 “
slice是引用类型就能改原 slice”:对s做s = append(s, x)不会影响调用方,因为append可能分配新底层数组,只改了副本里的ptr
真正容易被忽略的是:切片、map、channel 的“可变性”来自其内部指针字段,不是语言层面的引用传递;而 *[]T、*map[K]V 这类指针类型本身可比较,但 []T 和 map[K]V 不可比较——这点在做 map key 或单元测试断言时经常踩坑。
相关文章
- 天堂2盟约里巨蚁女王怎么打-天堂2盟约如何击败巨蚁女王 07-20
- 决胜之心 魂镜影介绍 07-20
- 迷你世界炎狱魔龙如何获得 炎狱魔龙技能图鉴 07-20
- 迷你世界厨房修建攻略 迷你世界厨房搭建方法 07-20
- 洛克王国世界s3赛季什么时候开始 07-20
- 绝区零希格莉德立绘合集 希格莉德值得抽吗 07-20