Value Receivers vs Pointer Receivers in Go(实用解释)

发布: (2026年2月10日 GMT+8 13:22)
5 分钟阅读
原文: Dev.to

Source: Dev.to

Introduction

在 Go 中,你首先会遇到的设计问题之一是:方法应该使用 值接收者 还是 指针接收者。这两种形式都很常见:

func (u User) Greet() {}
func (u *User) UpdateName() {}

虽然看起来相似,但选择会影响代码的正确性、性能以及类型在实际后端代码中的行为。

Value Receivers

在 Go 中,方法只是附加到类型上的函数。

type User struct {
    Name string
}

使用值接收者添加行为:

func (u User) Greet() {
    fmt.Println("Hello,", u.Name)
}

这里的 u 被称为 接收者;它是调用方法的值的副本。

user := User{Name: "Shivam"}
user.Greet()

Modifying a Value Receiver

当方法接收到的是副本时,任何修改只会影响该副本。

func (u User) ChangeName() {
    u.Name = "New Name"
}

示例

package main

import "fmt"

type User struct {
    Name string
}

func (u User) ChangeName() {
    u.Name = "New Name"
}

func main() {
    user := User{Name: "Shivam"}
    user.ChangeName()
    fmt.Println(user.Name) // Output: Shivam
}

输出仍然是 Shivam,因为方法作用于副本。
关键点: 值接收者 = 在副本上工作。

When to Use Value Receivers

  • 结构体很小。
  • 方法不需要修改接收者(只读辅助函数)。

一个典型的例子是 Point 类型:

func (p Point) Distance() float64 { /* ... */ }

Pointer Receivers

指针接收者让方法能够访问内存中的原始结构体。

func (u *User) ChangeName() {
    u.Name = "New Name"
}

示例

package main

import "fmt"

type User struct {
    Name string
}

func (u *User) ChangeName() {
    u.Name = "New Name"
}

func main() {
    user := User{Name: "Shivam"}
    user.ChangeName()
    fmt.Println(user.Name) // Output: New Name
}

更改会持久化,因为方法作用于原始对象。
关键点: 指针接收者 = 在原始对象上工作。

Advantages of Pointer Receivers

  • 状态修改: 需要更新字段的方法几乎总是应该使用指针接收者。
  • 性能: 对于大型结构体,避免在每次方法调用时进行昂贵的复制。
  • 接口实现: 带指针接收者的方法只属于指针类型,这会影响类型是否满足某个接口。

Choosing Between Value and Pointer Receivers

SituationRecommended Receiver
方法必须修改接收者的字段指针接收者 (*T)
结构体很大,复制成本高指针接收者
方法仅读取数据且结构体很小值接收者 (T)
需要实现要求指针方法的接口指针接收者

在实际项目中,对于表示后端系统真实实体的类型(服务、处理器、配置、数据库模型、控制器),指针接收者是默认选择。对于行为类似不可变数据的简单值类型,使用值接收者即可

Summary

  • 值接收者: 在副本上工作;方法内部的修改不会反映到外部。
  • 指针接收者: 在原始对象上工作;修改会持久化。
  • 当需要修改状态、避免复制大型结构体或满足需要指针方法的接口时,使用指针接收者。
  • 对于小型、只读的类型,使用值接收者。

一旦你内化了这一区别,在 Go 中设计方法就会变得直观易懂。

0 浏览
Back to Blog

相关文章

阅读更多 »

Go 模板

什么是 Go 模板?Go 模板是一种在 Go 中通过将数据与纯文本或 HTML 文件混合来创建动态内容的方式。它们允许您替换占位符……

新文章

您确定要隐藏此 comment 吗?它将在您的 post 中被隐藏,但仍可通过 comment 的 permalink 查看。Hide child comments 如我们……

设置 Ollama、NGROK 和 LangChain

!Breno A.https://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fu...