在 Go 语言中,方法的调用规则对于值接收者和指针接收者有一些特别的行为,这使得代码变得更加简洁和易用。我们来详细解释一下“方法值调用规则”和“方法表达式调用规则”,以及它们如何影响代码的行为。

方法值调用(Method Value Call)

在 Go 中,方法调用的语法是 receiver.method(). 当一个方法具有接收者时,Go 允许我们在值接收者和指针接收者之间进行一定程度的自动转换。这些转换规则使得方法调用更加灵活。

自动获取地址

当你调用一个接收者为指针的方法时,如果你持有的是一个值,Go 会自动获取这个值的地址并传递给方法。反过来,如果你调用一个接收者为值的方法时,持有的是指针,Go 会自动解引用指针并传递给方法。

举例解释

假设我们有以下结构体和方法:

type Example struct {
Value int
} func (e Example) ValueMethod() {
fmt.Println("ValueMethod called on", e.Value)
} func (e *Example) PointerMethod() {
fmt.Println("PointerMethod called on", e.Value)
}

值接收者方法调用

var ex Example
ex.ValueMethod() // 直接调用,传递值
(&ex).ValueMethod() // 自动解引用 ex,传递值

指针接收者方法调用

var ex Example
ex.PointerMethod() // 自动获取 ex 的地址,传递指针
(&ex).PointerMethod() // 直接传递指针

在代码中的应用

type People struct{}

func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
} func (p *People) ShowB() {
fmt.Println("showB")
} type Teacher struct {
People
} func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
} func main() {
t := Teacher{}
t.ShowB()
}
  • t := Teacher{} 创建了一个 Teacher 类型的值。
  • t.ShowB() 调用 TeacherShowB() 方法,尽管 ShowB 的接收者是 *Teacher 类型的指针,Go 自动获取 t 的地址并传递给方法,因此调用的是 (&t).ShowB()
type People struct{}

func (p People) ShowA() {
fmt.Println("showA")
p.ShowB()
} func (p People) ShowB() {
fmt.Println("showB")
} type Teacher struct {
People
} func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
} func main() {
t := &Teacher{}
t.ShowB()
}
  • 这样也能正常输出

为什么可以这样?

这是因为 Go 编译器知道 ShowB 方法需要一个指针接收者,并且在 t 是一个值时,它会自动获取 t 的地址以符合方法的签名。这使得方法调用更加直观,无需显式地获取地址。

总结

  • 值接收者方法:可以使用值或者指针来调用。
  • 指针接收者方法:可以使用指针或者值来调用,Go 会自动获取地址。

这种自动转换规则使得方法调用变得更加简洁,不需要显式地在值和指针之间转换,从而减少了代码的复杂性和易错性。

Go 语言中值接收者和指针接收者方法调用的自动转换规则详解的更多相关文章

  1. UIViewController中各方法调用顺序及功能详解

    UIViewController中各方法调用顺序及功能详解 UIViewController中loadView, viewDidLoad, viewWillUnload, viewDidUnload, ...

  2. 转:UIViewController中各方法调用顺序及功能详解

    UIViewController中loadView, viewDidLoad, viewWillUnload, viewDidUnload, viewWillAppear, viewDidAppear ...

  3. C++中值传递、指针传递、引用传递的总结

    C++中值传递.指针传递.引用传递的总结   指针传递和引用传递一般适用于:函数内部修改参数并且希望改动影响调用者.对比值传递,指针/引用传递可以将改变由形参"传给"实参(实际上就 ...

  4. R语言中样本平衡的几种方法

    R语言中样本平衡的几种方法 在对不平衡的分类数据集进行建模时,机器学习算法可能并不稳定,其预测结果甚至可能是有偏的,而预测精度此时也变得带有误导性.在不平衡的数据中,任一算法都没法从样本量少的类中获取 ...

  5. 机器学习中的隐马尔科夫模型(HMM)详解

    机器学习中的隐马尔科夫模型(HMM)详解 在之前介绍贝叶斯网络的博文中,我们已经讨论过概率图模型(PGM)的概念了.Russell等在文献[1]中指出:"在统计学中,图模型这个术语指包含贝叶 ...

  6. JSON创建键值对(key是中文或者数字)方式详解

    JSON创建键值对(key是中文或者数字)方式详解 先准备好一个空的json对象 var obj = {}; 1. 最原始的方法 obj.name = 'zhangsan'; //这种方式很简单的添加 ...

  7. Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

    Opencv中Mat矩阵相乘——点乘.dot.mul运算详解 2016年09月02日 00:00:36 -牧野- 阅读数:59593 标签: Opencv矩阵相乘点乘dotmul 更多 个人分类: O ...

  8. 【翻译】Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解)

    [翻译]Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解) . . .

  9. MySQL中tinytext、text、mediumtext和longtext等各个类型详解

    转: MySQL中tinytext.text.mediumtext和longtext等各个类型详解 2018年06月13日 08:55:24 youcijibi 阅读数 26900更多 个人分类: 每 ...

  10. JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解

    在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...

随机推荐

  1. Python threading实现多线程 基础篇

    讲多线程前,先要了解什么是进程,什么是线程,已经知道的请略过. 一.进程与线程: 进程是资源分配的最小单位,一个程序至少有一个进程. 线程是程序执行的最小单位,一个进程至少有一个线程. 进程都有自己独 ...

  2. 人工智能时代,前端全栈成就独立开发工程师 next.js 开发实战

    next  可以服务端渲染,可以客户端渲染,让前端同事更有性价比,让我们做得可以更多 由于next.js 是基础于react 所以在正式学习next.js 之前我们了解一下react 什么叫模块 ,就 ...

  3. 3、SpringBoot2之配置文件

    3.1.环境搭建 3.1.1.在project创建新module 3.1.2.选择maven 3.1.3.设置module名称和路径 3.1.4.module初始状态 3.1.5.引入springbo ...

  4. python报错:Pip 20.3+ break proxy connection

    参考: https://www.cnblogs.com/devilmaycry812839668/p/17872452.html =================================== ...

  5. 【Playwright+Python】系列教程(八)鉴权Authentication的使用

    写在前面 还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物. 读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维. 到底是什么意思? 就是你已经登陆过一次,在 ...

  6. 使用 defineNuxtRouteMiddleware 创建路由中间件

    title: 使用 defineNuxtRouteMiddleware 创建路由中间件 date: 2024/8/10 updated: 2024/8/10 author: cmdragon exce ...

  7. 这次轮到AntV增强Awesome-Graphs

    前不久,Awesome-Graphs刚Release完1.1.0版本后,我在<从论文到图谱,或许只差一个html>一文中,向大家详细展示了Awesome-Graphs的产品能力与交互形态. ...

  8. MFC状态栏的创建与添加进度条

    1.首先要创建状态栏 MFC中创建状态栏是用数组来分隔格子的.所以要先弄个数组 下面在自己继承的CWnd类.cpp文件中定义一个静态数组indicators static UINT indicator ...

  9. Devexpress 控件学习记录(一:BarManager 控件、XtraTabbedMdiManager 控件)

    BarManager 控件 最终实现的效果如下: 首先在窗体中拖出BarManager控件,窗体Bar add地方点击添加 设置BarManager的属性 设置出现的窗体的底部[DockStyle=B ...

  10. C# JSON序列化指定名称

    今天在做项目时遇到了要将json对象序列化为数据库表,  结果数据库表和json对象数据类型和字段名称对不上.于是就有了一下的解决方案: 需要转化的对象 { "orgAccountId&qu ...