全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-14 6 分钟 ✍️ juanwangdev

Go值接收者与指针接收者

方法接收者类型决定方法能否修改原值,影响接口满足规则。

值接收者

定义与行为

Go
type User struct {
    Name string
    Age  int
}

func (u User) GetName() string {
    return u.Name  // 读取,OK
}

func (u User) SetAge(age int) {
    u.Age = age  // 修改副本,无效!
}

u := User{Name: "Tom", Age: 25}
u.SetAge(30)
fmt.Println(u.Age)  // 25(未改变)

值接收者操作副本,修改不影响原值。

特点

  • 方法内操作的是副本
  • 读取有效,修改无效
  • 方法调用不修改原值
  • 适合只读操作

指针接收者

定义与行为

Go
func (u *User) SetAge(age int) {
    u.Age = age  // 修改原值,有效!
}

func (u *User) SetName(name string) {
    u.Name = name  // 修改原值,有效!
}

u := User{Name: "Tom", Age: 25}
u.SetAge(30)  // 自动转换为(&u).SetAge(30)
fmt.Println(u.Age)  // 30(已改变)

指针接收者操作原值,修改有效。

特点

  • 方法内操作的是原值
  • 读取和修改都有效
  • 可以修改接收者状态
  • 适合需要修改的场景

自动转换规则

值调用方法

Go
u := User{Name: "Tom"}

// 值调用值接收者方法:直接调用
u.GetName()  // OK

// 值调用指针接收者方法:自动转换为指针
u.SetAge(30)  // 自动转换为(&u).SetAge(30)

指针调用方法

Go
u := &User{Name: "Tom"}

// 指针调用指针接收者方法:直接调用
u.SetAge(30)  // OK

// 指针调用值接收者方法:自动解引用
u.GetName()  // 自动转换为(*u).GetName()

Go自动处理值/指针调用的转换,但接口赋值不自动转换。

选择原则

使用指针接收者的场景

Go
// 1. 需要修改接收者
func (u *User) SetAge(age int) {
    u.Age = age
}

// 2. 接收者较大(避免复制)
type BigData struct {
    Data [10000]byte
}

func (b *BigData) Process() {
    // 指针避免大结构体复制
}

// 3. 保持一致性(其他方法用指针)
func (u *User) Method1() {}
func (u *User) Method2() {}  // 统一用指针

使用值接收者的场景

Go
// 1. 只读取不修改
func (u User) GetName() string {
    return u.Name
}

// 2. 接收者较小(复制成本低)
type Point struct {
    X, Y int
}

func (p Point) Distance() float64 {
    // 小结构体,复制成本低
}

// 3. 不需要修改且值语义清晰
func (t Time) Format() string {
    // 时间格式化,不需要修改
}

接收者选择对比

场景推荐原因
需修改接收者指针唯一能修改的方式
大结构体指针避免复制开销
小结构体只读复制成本低
保持一致性统一避免混用混乱
基础类型本质是值语义

接口满足差异

值接收者

Go
type Reader interface {
    Read() string
}

type MyReader struct{}

func (m MyReader) Read() string { return "data" }

// 值和指针都满足接口
var r Reader = MyReader{}   // ✓
var r Reader = &MyReader{}  // ✓

指针接收者

Go
type Writer interface {
    Write(data string)
}

type MyWriter struct{}

func (m *MyWriter) Write(data string) {}

// 只有指针满足接口
var w Writer = MyWriter{}   // ✗ 编译错误
var w Writer = &MyWriter{}  // ✓

最佳实践示例

Go
type Counter struct {
    value int
}

// 值接收者:只读操作
func (c Counter) Value() int {
    return c.value
}

// 指针接收者:修改操作
func (c *Counter) Increment() {
    c.value++
}

func (c *Counter) Reset() {
    c.value = 0
}

要点总结

  • 值接收者操作副本,修改无效
  • 指针接收者操作原值,修改有效
  • 方法调用时Go自动转换值/指针
  • 接口赋值不自动转换指针
  • 指针接收者:值类型不满足接口
  • 值接收者:值和指针都满足接口
  • 选择原则:需修改用指针,只读用值
  • 大结构体推荐指针,避免复制开销
  • 同一类型方法保持接收者一致性

📝 发现内容有误?点击此处直接编辑

← 上一篇 Go结构体
下一篇 → Go接口与多态
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库