一文详解Go语言中方法的指针接收者与值接收者

 更新时间:2025年06月10日 09:54:26   作者:tekin  
在 Go 语言里,方法是一种特殊的函数,它与特定的类型关联,方法可以使用值接收者或者指针接收者,理解这两种接收者的区别和使用场景,对于编写高效、正确的 Go 代码至关重要,本文将深入剖析指针接收者和值接收者的特点,需要的朋友可以参考下

基本概念

值接收者

值接收者在方法调用时,会复制一份接收者的值。这意味着在方法内部对接收者的修改不会影响到原始值。值接收者的方法定义语法如下:

func (t Type) MethodName(parameters) returnType {
    // 方法体
}

其中,t 是接收者的实例,Type 是接收者的类型。

指针接收者

指针接收者在方法调用时,传递的是接收者的地址。因此,在方法内部对接收者的修改会影响到原始值。指针接收者的方法定义语法如下:

func (t *Type) MethodName(parameters) returnType {
    // 方法体
}

这里的 t 是指向接收者实例的指针。

代码示例

值接收者示例

package main

import "fmt"

// Rectangle 定义一个矩形结构体
type Rectangle struct {
    width  float64
    height float64
}

// Area 使用值接收者计算矩形面积
func (r Rectangle) Area() float64 {
    return r.width * r.height
}

// SetWidth 使用值接收者尝试修改矩形宽度
func (r Rectangle) SetWidth(width float64) {
    r.width = width
}

func main() {
    rect := Rectangle{width: 10, height: 5}
    fmt.Println("原始矩形面积:", rect.Area())

    rect.SetWidth(20)
    fmt.Println("尝试修改宽度后矩形面积:", rect.Area())
}

在上述代码中,Area 方法使用值接收者计算矩形面积,SetWidth 方法使用值接收者尝试修改矩形宽度。但由于是值接收者,SetWidth 方法内部的修改不会影响到原始的 rect 实例。

指针接收者示例

package main

import "fmt"

// Rectangle 定义一个矩形结构体
type Rectangle struct {
    width  float64
    height float64
}

// Area 使用值接收者计算矩形面积
func (r Rectangle) Area() float64 {
    return r.width * r.height
}

// SetWidth 使用指针接收者修改矩形宽度
func (r *Rectangle) SetWidth(width float64) {
    r.width = width
}

func main() {
    rect := Rectangle{width: 10, height: 5}
    fmt.Println("原始矩形面积:", rect.Area())

    (&rect).SetWidth(20)
    fmt.Println("使用指针接收者修改宽度后矩形面积:", rect.Area())
}

这里的 SetWidth 方法使用指针接收者,对 rect 实例的修改会反映到原始值上。

选择指针接收者还是值接收者

需要修改接收者时

如果方法需要修改接收者的状态,必须使用指针接收者。例如,在一个银行账户结构体中,取款和存款操作会改变账户的余额,就应该使用指针接收者。

package main

import "fmt"

// Account 定义银行账户结构体
type Account struct {
    balance float64
}

// Deposit 使用指针接收者进行存款操作
func (a *Account) Deposit(amount float64) {
    a.balance += amount
}

// Withdraw 使用指针接收者进行取款操作
func (a *Account) Withdraw(amount float64) {
    if a.balance >= amount {
        a.balance -= amount
    } else {
        fmt.Println("余额不足")
    }
}

// Balance 使用值接收者获取账户余额
func (a Account) Balance() float64 {
    return a.balance
}

func main() {
    account := Account{balance: 1000}
    fmt.Println("初始余额:", account.Balance())

    account.Deposit(500)
    fmt.Println("存款后余额:", account.Balance())

    account.Withdraw(200)
    fmt.Println("取款后余额:", account.Balance())
}

接收者是大结构体时

如果接收者是一个大结构体,使用值接收者会导致大量的数据复制,影响性能。此时应该使用指针接收者,避免复制带来的开销。

一致性考虑

如果一个类型的某些方法使用了指针接收者,为了保持一致性,其他方法也应该使用指针接收者。

项目场景中的应用

图形绘制系统

在图形绘制系统中,图形对象(如矩形、圆形等)可能需要进行移动、缩放等操作,这些操作会改变图形对象的状态,因此应该使用指针接收者。而一些计算图形属性(如面积、周长)的方法可以使用值接收者。

package main

import "fmt"

// Circle 定义圆形结构体
type Circle struct {
    x      float64
    y      float64
    radius float64
}

// Area 使用值接收者计算圆形面积
func (c Circle) Area() float64 {
    return 3.14 * c.radius * c.radius
}

// Move 使用指针接收者移动圆形位置
func (c *Circle) Move(dx, dy float64) {
    c.x += dx
    c.y += dy
}

func main() {
    circle := Circle{x: 0, y: 0, radius: 5}
    fmt.Println("原始圆形面积:", circle.Area())

    circle.Move(10, 20)
    fmt.Printf("移动后圆形位置: (%f, %f)\n", circle.x, circle.y)
}

缓存系统

在缓存系统中,缓存对象可能需要进行更新、删除等操作,这些操作会改变缓存对象的状态,应该使用指针接收者。而获取缓存值的方法可以使用值接收者。

package main

import "fmt"

// Cache 定义缓存结构体
type Cache struct {
    data map[string]interface{}
}

// NewCache 创建一个新的缓存实例
func NewCache() *Cache {
    return &Cache{
        data: make(map[string]interface{}),
    }
}

// Set 使用指针接收者设置缓存值
func (c *Cache) Set(key string, value interface{}) {
    c.data[key] = value
}

// Get 使用值接收者获取缓存值
func (c Cache) Get(key string) (interface{}, bool) {
    val, exists := c.data[key]
    return val, exists
}

func main() {
    cache := NewCache()
    cache.Set("key1", "value1")

    val, exists := cache.Get("key1")
    if exists {
        fmt.Println("缓存值:", val)
    } else {
        fmt.Println("缓存中不存在该键")
    }
}

总结

Go 语言中的指针接收者和值接收者各有其特点和适用场景。值接收者适用于不需要修改接收者状态、接收者较小的情况;指针接收者适用于需要修改接收者状态、接收者较大的情况。在实际项目中,需要根据具体需求和性能考虑来选择合适的接收者类型。同时,为了保持代码的一致性,一个类型的方法尽量统一使用指针接收者或值接收者。通过合理运用指针接收者和值接收者,开发者可以编写出高效、正确的 Go 代码。

以上就是一文详解Go语言中方法的指针接收者与值接收者的详细内容,更多关于Go方法的指针与值接收者的资料请关注脚本之家其它相关文章!

相关文章

  • Go读取配置文件的方法总结

    Go读取配置文件的方法总结

    我们常见的配置文件的格式一般有:XML、JSON、INI、YAML、env和.properties,本文小编为大家整理了Go语言读取这些格式的配置文件的方法,希望对大家有所帮助
    2023-10-10
  • Golang极简入门教程(二):方法和接口

    Golang极简入门教程(二):方法和接口

    这篇文章主要介绍了Golang极简入门教程(二):方法和接口,本文同时讲解了错误、匿名域等内容,需要的朋友可以参考下
    2014-10-10
  • Go语言编程中对文件读写的基本方法整理

    Go语言编程中对文件读写的基本方法整理

    这篇文章主要介绍了Go语言编程中对文件读写的基本方法整理,是Go语言入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10
  • go-cqhttp环境配置及安装过程

    go-cqhttp环境配置及安装过程

    这篇文章主要介绍了go-cqhttp环境配置,包括go-cqhttp安装及简单介绍,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • golang方法中receiver为指针与不为指针的区别详析

    golang方法中receiver为指针与不为指针的区别详析

    这篇文章主要给大家介绍了关于golang方法中receiver为指针与不为指针区别的相关资料,其实最大的区别应该是指针传递的是对像的引用,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • 一步步教你编写可测试的Go语言代码

    一步步教你编写可测试的Go语言代码

    相信每位编程开发者们应该都知道,Golang作为一门标榜工程化的语言,提供了非常简便、实用的编写单元测试的能力。本文通过Golang源码包中的用法,来学习在实际项目中如何编写可测试的Go代码。有需要的朋友们可以参考借鉴,下面跟着小编一起去学习学习吧。
    2016-11-11
  • 使用Golang轻松实现JWT身份验证的示例代码

    使用Golang轻松实现JWT身份验证的示例代码

    JSON Web Tokens (JWT)是一种流行的安全方法,用于在两个方之间表示声明,本文主要为大家详细介绍了实现Go应用程序中的JWT身份验证过程,需要的可以参考下
    2024-02-02
  • golang如何自定义json序列化应用详解

    golang如何自定义json序列化应用详解

    son格式可以算我们日常最常用的序列化格式之一了,下面这篇文章主要给大家介绍了关于golang如何自定义json序列化应用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧
    2018-08-08
  • Golang中int类型和字符串类型相互转换的实现方法

    Golang中int类型和字符串类型相互转换的实现方法

    在日常开发中,经常需要将数字转换为字符串或者将字符串转换为数字,在 Golang 中,有一些很简便的方法可以实现这个功能,接下来就详细讲解一下如何实现 int 类型和字符串类型之间的互相转换,需要的朋友可以参考下
    2023-09-09
  • golang 四则运算计算器yacc归约手写实现

    golang 四则运算计算器yacc归约手写实现

    这篇文章主要为大家介绍了golang 四则运算 计算器 yacc 归约的手写实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07

最新评论