Golang指针基础怎么理解_pointer入门讲解

2026-01-28 00:00:00 作者:P粉602998670
指针是存储地址的变量,Go中只有值传递,传指针即传地址值;必须用指针的两种场景是修改原值和避免大对象拷贝;结构体方法接收者选* T还是T取决于是否修改字段及接口一致性。

指针就是存地址的变量,不是值本身

Go 里没有“引用传递”,只有值传递;但你可以传一个「地址的值」——这就是指针。它不神秘,就是一个占 4 或 8 字节的变量,里面存着另一个变量在内存里的位置。

  • & 只能作用于**变量**(比如 &x),不能对字面量用(&42&"hello" 都报错)
  • * 在声明时是类型修饰符(var p *int),在使用时是解引用(*p = 10)——上下文决定含义
  • 未初始化的指针默认是 nil,直接 fmt.Println(*p) 就 panic

什么时候必须用指针?看两个硬需求

传指针不是为了“高级”,而是解决两个具体问题:改原值,或省拷贝。

  • 需要修改调用方的数据 → 比如 func increment(p *int) { *p++

    }
    ,不传 *int 就改不动 main 里的变量
  • 避免大对象复制 → 结构体含 []bytemap[string]interface{} 或字段超过 3–4 个时,传 *UserUser 快得多也安全得多
  • 基础类型(intstring、小 struct)传指针反而拖慢性能,还多一层 nil 判断负担

结构体方法接收者选 *T 还是 T?别猜,看行为

这不是风格问题,是语义和接口兼容性问题。

  • 要改字段(SetNameReset)→ 必须用 func (u *User) SetName(n string)
  • 只读计算(FullName()IsValid())→ func (u User) FullName() 更轻量、更安全
  • 只要有一个方法用了 *User 接收者,那所有方法最好统一用 *User,否则 User 值类型无法满足含指针方法的接口

最容易踩的三个坑,都在循环和返回值里

这些错误不会编译失败,但运行时出问题,而且极难 debug。

  • 循环中取局部变量地址:for _, name := range names { u := User{Name: name}; m[name] = &u } → 所有 key 都指向最后一次迭代的 u
  • 正确写法是:m[name] = &User{Name: name}(Go 逃逸分析自动分配到堆,每个都是独立地址)
  • 函数返回局部变量地址:func bad() *int { v := 42; return &v } → Go 编译器会捕获并报错,但类似逻辑(比如闭包捕获循环变量)仍可能漏掉

指针本身很简单,难的是判断「该不该用」和「用得对不对」——尤其是当多个 goroutine 共享一个 *Config 时,是否加锁、是否深拷贝、是否允许并发写,这些才是真实项目里卡住人的地方。

猜你喜欢

联络方式:

400 9058 355

邮箱:8955556@qq.com

Q Q:8955556

微信二维码
在线咨询 拨打电话

电话

400 9058 355

微信二维码

微信二维码