0

0

Go 语言中结构体方法:值接收者与指针接收者的区别

聖光之護

聖光之護

发布时间:2025-08-03 19:04:01

|

216人浏览过

|

来源于php中文网

原创

go 语言中结构体方法:值接收者与指针接收者的区别

本文旨在帮助 Go 语言开发者理解结构体方法中值接收者和指针接收者的关键差异。通过分析示例代码,我们可以看到,值接收者方法操作的是结构体的副本,而指针接收者方法直接操作原始结构体。理解这一点对于编写高效、正确的 Go 代码至关重要。

值接收者与指针接收者

在 Go 语言中,我们可以为结构体定义方法。定义方法时,需要指定接收者(receiver),接收者可以是结构体的值(值接收者)或指向结构体的指针(指针接收者)。这两种接收者类型在使用上存在显著差异,尤其是在修改结构体字段时。

值接收者方法

当使用值接收者时,方法接收的是结构体的一个副本。这意味着在方法内部对结构体字段的任何修改都不会影响原始结构体。

package main

import "fmt"

type T struct {
    Val string
}

// 值接收者方法
func (t T) SetVal(s string) {
    t.Val = s // 修改的是 t 的副本
}

func main() {
    v := T{"abc"}
    fmt.Println(v) // 输出: {abc}
    v.SetVal("pdq")
    fmt.Println(v) // 输出: {abc},Val 字段未被修改
}

在上面的例子中,SetVal 方法使用值接收者 (t T)。当调用 v.SetVal("pdq") 时,Go 会创建 v 的一个副本 t,并在 SetVal 方法内部修改 t.Val。由于 v 和 t 是不同的变量,因此对 t.Val 的修改不会反映到 v.Val 上。

指针接收者方法

当使用指针接收者时,方法接收的是指向结构体的指针。这意味着在方法内部对结构体字段的修改会直接影响原始结构体。

package main

import "fmt"

type T struct {
    Val string
}

// 指针接收者方法
func (t *T) SetVal(s string) {
    t.Val = s // 修改的是 *t 指向的结构体
}

func main() {
    v := T{"abc"}
    fmt.Println(v) // 输出: {abc}
    v.SetVal("pdq")
    fmt.Println(v) // 输出: {pdq},Val 字段被修改
}

在上面的例子中,SetVal 方法使用指针接收者 (t *T)。当调用 v.SetVal("pdq") 时,Go 会将 v 的地址传递给 SetVal 方法。在 SetVal 方法内部,t 是指向 v 的指针,因此 t.Val = s 实际上是修改了 v.Val。

NotebookLM
NotebookLM

Google推出的AI笔记应用工具

下载

地址验证

为了进一步验证值接收者和指针接收者的差异,我们可以打印出结构体的地址:

package main

import "fmt"

type T struct {
    Val string
}

func (t T) SetVal(s string) {
    fmt.Printf("值接收者地址: %p\n", &t)
    t.Val = s
}

func (t *T) SetVal2(s string) {
    fmt.Printf("指针接收者地址: %p\n", t)
    t.Val = s
}

func main() {
    v := T{"abc"}
    fmt.Printf("原始结构体地址: %p\n", &v)
    v.SetVal("pdq")
    v.SetVal2("xyz")
    fmt.Println(v)
}

运行结果可能如下:

原始结构体地址: 0x地址1
值接收者地址: 0x地址2
指针接收者地址: 0x地址1
{xyz}

可以看到,值接收者方法中结构体的地址与原始结构体的地址不同,而指针接收者方法中结构体的地址与原始结构体的地址相同。这证实了值接收者方法操作的是结构体的副本,而指针接收者方法操作的是原始结构体。

何时使用值接收者,何时使用指针接收者?

  • 需要修改结构体字段时: 必须使用指针接收者。
  • 只需要读取结构体字段,不需要修改时: 可以使用值接收者。使用值接收者可以避免不必要的内存分配和拷贝,提高性能。
  • 结构体较大时: 建议使用指针接收者,避免拷贝大型结构体带来的性能开销。
  • 方法需要满足接口要求时: 需要根据接口的定义来选择值接收者或指针接收者。

总结

理解 Go 语言中结构体方法的值接收者和指针接收者的区别至关重要。值接收者方法操作的是结构体的副本,而指针接收者方法操作的是原始结构体。在需要修改结构体字段时,必须使用指针接收者。选择合适的接收者类型可以提高代码的效率和可维护性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

282

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

192

2025.07.04

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1206

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

235

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2180

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.01.19

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

32

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

23

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号