如何使用Golang实现函数接收指针_修改外部变量值的技巧

12次阅读

go函数默认值传递,修改原变量需传指针;仅可寻址变量能取地址;指针参数名和函数名应体现修改意图并检查nil结构体优先传指针;切片/map/channel本身引用语义,但替换底层数组需指针。

如何使用Golang实现函数接收指针_修改外部变量值的技巧

在 Go 语言中,函数默认按值传递参数,若想在函数内部修改调用方的变量值,必须传入该变量的指针。这不是“技巧”,而是 Go 的核心设计原则——明确性与可控性。关键在于理解何时取地址、何时解引用,以及避免常见陷阱(比如对 nil 指针解引用或误传值类型地址)。

传指针前先确认变量可寻址

只有可寻址的变量才能取地址(即能写 &x)。常量、字面量、函数返回值(非地址)、map 中的元素(除非是结构体字段且 map 已初始化)、接口值本身等都不可寻址。

  • ✅ 正确:定义变量后传其地址
  • ❌ 错误:modify(&42)(字面量不可取地址)或 modify(&m["key"])(map 元素不可寻址,除非是 &StructField 且 struct 在 map 中)

函数签名要清晰表达“会修改输入”

接收指针的参数名和函数名应体现意图。例如用 incrementcounterdoSomething 更明确;参数可命名为 count *int 而非 v *int

同时,务必检查指针是否为 nil,尤其当指针可能来自外部调用时:

立即学习go语言免费学习笔记(深入)”;

func incrementCounter(count *int) {     if count == nil {         return // 或 panic("count is nil"),依业务而定     }     *count++ }

结构体指针是高频场景,优先使用

对于结构体,传指针既避免复制开销,又自然支持字段修改。方法接收者也常用指针,以保证修改生效:

type User struct {     Name string     Age  int }  func (u *User) GrowOld() {     u.Age++ }  func main() {     u := User{Name: "Alice", Age: 30}     u.GrowOld() // ✅ 方法内修改了原始 u 的 Age     fmt.Println(u.Age) // 输出 31 }

注意:如果方法接收者是 func (u User)(值接收者),u.Age++ 只修改副本,原结构体不变。

切片、map、channel 本身含引用语义,通常不需额外传指针

切片底层指向数组,修改元素(如 s[0] = 1)会影响原切片;map 和 channel 同理。但若需替换整个底层数组(如扩容后重新赋值给原变量),仍需指针:

func appendAndReplace(s *[]int, x int) {     *s = append(*s, x) }  func main() {     data := []int{1, 2}     appendAndReplace(&data, 3)     fmt.Println(data) // [1 2 3] }

这里 &data 是因为 append 可能分配新底层数组,必须通过指针把新地址写回原变量。

text=ZqhQzanResources