我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go方法接收者值接收者与指针接收者详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go方法接收者值接收者与指针接收者详解

引言

在review 一些代码中,发现经常某个类型定义的方法,其接收者既有值类型,又有指针类型,然后 Goland 就有提示: Struct Person has methods on both value and pointer receivers. Such usage is not recommended by the Go Documentation.

一般来讲,这个提示对代码的运行并不会产生什么问题。只不过对于有轻微 “代码洁癖” 的人来讲,体感不好,就一定想要改统一。

当然,我并不是想讲要统一的问题,前面说这么多废话,只是为了铺垫一下引出本文的内容:Go中的值接收者与指针接收者有什么关系与区别,该怎么选?

联系与区别

在继续讲下去之前,我们得先明确,Go 里边能够定义方法的必须是自定义类型,而不能是系统内置类型,比如 int、string 这种是不可以为其添加方法的。

那么当我们定义了一个自定义类型,可以为其添加方法,先上代码:

package main
import "fmt"
type Person struct {
   name string
   age  int
}
// 值针接收者
func (p Person) GetName() string {
   return p.name
}
// 指针接收者
func (p *Person) GetAge() int {
   return p.age
}
func main() {
   //  定义了一个【值类型】
   t := Person{
      name: "DaYu",
      age:  int(28),
   }
   // 调用值方法
   fmt.Println(t.GetName())
   // 调用指针方法
   fmt.Println(t.GetAge())
}
-----运行结果-------
study/demo01/client go run *
DaYu
28

指针类型调用结果

从使用过程看,值类型的变量,可以调用该类型的值接收者方法,也可以调用指针接收者方法。

反之,我们可以定义一个指针类型,然后看看调用结果:

package main
import "fmt"
type Person struct {
   name string
   age  int
}
func (p *Person) GetName() string {
   return p.name
}
func (p Person) GetAge() int {
   return p.age
}
func main() {
   // 注意,其它地方都没有改,只是这里改变了类型
   t := &Person{
      name: "DaYu",
      age:  int(28),
   }
   fmt.Println(t.GetName())
   fmt.Println(t.GetAge())
}
-----运行结果-------
study/demo01/client go run *
DaYu
28

这段代码告诉我们,指针类型的变量,可以调用该类型的值接收者方法,也可以调用指针接收者方法。

是不是特别有意思?

  • 值类型变量,可以调用值接收的方法,也可以调用指针接收者的方法;
  • 指针类型变量,可以调用值接收的方法,也可以调用指针接收者的方法。

看起来好像两者对等的,并没有差别。那么二者真的没有差别吗?只是一种表达形式上的差异?其实不然,如果引入接口类型后,我们再来看看。

package main
// 新增的接口
type Animal interface {
   GetName() string
   GetAge() int
}
type Person struct {
   name string
   age  int
}
func (p *Person) GetName() string {
   return p.name
}
func (p Person) GetAge() int {
   return p.age
}
func main() {
   // 定义的接口变量
   var ani Animal
   // person 实现了 Animal 接口,赋值给了 ani 变量
   // 但是,这里编译会通不过,错误如下:
   // Cannot use 'Person{ name: "DaYu", age: int(28), }' (type Person) as the type Animal Type does not implement 'Animal' as the 'GetName' method has a pointer receiver
   ani = Person{
      name: "DaYu",
      age:  int(28),
   }
   ani.GetName()
   ani.GetAge()
}

为什么会报错呢? 错误提醒很明显了:Person 没有实现 Animal 的 GetName 方法。因为在上面的代码中,我们实现 GetName 方法的是 (*Person) 类型。

但是为什么 GetAge 方法不报错呢? 那是因为 Go 里边对于 (Type)Method 的方法,会自动让他拥有 (*Type)Method 方法的能力。

实现接口时约束

  • 如果定义的是 (Type)Method,则该类型会隐式的声明一个 (*Type)Method;
  • 如果定义的是 (*Type)Method ,则不会隐式什么一个 (Type)Method。

至于为什么不也隐式申明一个 (Type)Method ,我觉得有一个原因是,我们一般采用指针接收者时,方法内部改变的值,接收者本身也会改变,那么此时如果隐式有这样一个申明,外部使用值类型时,这个改变就不会生效,语义上就会非常奇怪。

该怎么用

从使用表现上看,指针接收者在方法内部的改变,会体现到其本身。但这并不是决定我们要不要用指针接收者的唯一理由! 最重要的还是看接收者要不要全局共享一个实体,其次某些场景下,如果接收者本身太大,拷贝成本很高,也应该使用指针接收者。

回到文档开篇的问题,为什么不建议值接收者、指针接收者混用,主要还是在于语义不够清晰,存在潜在理解成本的问题。

以上就是Go方法接收者值接收者与指针接收者详解的详细内容,更多关于Go方法值接收者指针接收者的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Go方法接收者值接收者与指针接收者详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Go 一般方法与接口方法接收者的差异详解

这篇文章主要为大家介绍了Go 一般方法与接口方法接收者的差异详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-20

Go 中的指针与值接收器 | heap.Interface 与 sort.Interface

对于一个Golang开发者来说,牢固扎实的基础是十分重要的,编程网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Go 中的指针与值接收器 | heap.Interface 与 sort.Interface》,主要介绍了,希望对大
Go 中的指针与值接收器 | heap.Interface 与 sort.Interface
2024-04-05

Android入门:广播发送者与广播接收者详细介绍

一、广播发送者&广播接收者介绍 1.广播接收者 广播接收者简单地说就是接收广播意图的Java类,此Java类继承BroadcastReceiver类,重写:public void onReceive(Context context,Inte
2022-06-06

不同语言中方法接收器与Go语言方法接收器的差异

go 语言中的方法接收器与其他编程语言中的方法接收器不同。在 go 语言中:方法接收器位于函数签名中,紧接函数名。方法接收器是一个值,而不是指针,这使其更轻量级。不同语言中方法接收器与 Go 语言方法接收器在面向对象编程中,方法接收器允许
不同语言中方法接收器与Go语言方法接收器的差异
2024-04-12

Go:如何指定类型约束,其中方法的参数类型与接收者的类型相同

在Go语言中,我们可以使用类型约束来指定函数或方法的参数类型。当我们希望方法的参数类型与接收者的类型相同时,该如何指定呢?首先,需要明确的是,Go语言中并没有直接支持参数类型与接收者类型相同的特性。然而,我们可以通过在方法定义中使用指针类型
Go:如何指定类型约束,其中方法的参数类型与接收者的类型相同
2024-02-09

kafka消费者kafka-console-consumer接收不到数据的解决

这篇文章主要介绍了kafka消费者kafka-console-consumer接收不到数据的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-07

kafka消费者kafka-console-consumer接收不到数据如何解决

这篇“kafka消费者kafka-console-consumer接收不到数据如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看
2023-07-05

Go - 强制接口仅由方法上带有指针接收器的类型满足?

php小编百草为您介绍Go语言中的强制接口规则,即只有方法上带有指针接收器的类型才能满足接口的要求。Go语言是一门静态类型的编程语言,它通过接口来实现多态性。在定义接口时,可以指定方法的接收器类型,可以是值类型或指针类型。但是,当我们使用强
Go - 强制接口仅由方法上带有指针接收器的类型满足?
2024-02-10

一文详解Go中方法接收器的选择

许多Go初学者在方法接收器的选择上可能会感到困惑,不知道该选择值接收器还是指针接收器。本文将会对方法接收器进行介绍,并给出如何选择正确方法接收器的指导建议,希望对大家有所帮助
2023-05-17

Android编程四大组件之BroadcastReceiver(广播接收者)用法实例

本文实例讲述了Android编程四大组件之BroadcastReceiver(广播接收者)用法。分享给大家供大家参考,具体如下: 这里介绍如何创建广播、如何发送一个无序广播和有序广播、以及监听短信以及监听呼出电话(当我们发短信和打电话,系统
2022-06-06

X 没有实现 Y(...方法有一个指针接收器)

php小编小新在这篇文章中将探讨一个关于X未能实现Y的问题。在这个问题中,我们使用了一个指针接收器的方法。通过这个方法,我们可以更好地理解为什么X无法实现Y,并且找到解决这个问题的方法。在接下来的内容中,我们将详细讨论这个问题,并提供一些解
X 没有实现 Y(...方法有一个指针接收器)
2024-02-13

Protobuf消息没有实现protoreflect.ProtoMessage(ProtoReflect方法有指针接收器)

php小编新一在这里为大家介绍一种问题:在Protobuf消息中,我们发现没有实现protoreflect.ProtoMessage接口的ProtoReflect方法,而该方法使用了指针接收器。这个问题可能会导致一些困惑和不便。在文章中,我
Protobuf消息没有实现protoreflect.ProtoMessage(ProtoReflect方法有指针接收器)
2024-02-09

PHP无法接收参数的解决方法详解

PHP是一种非常流行的服务器端脚本语言,被广泛用于开发动态网站和Web应用程序。然而,有时候在使用PHP接收参数时会遇到一些问题,比如无法接收到期望的参数。本文将详细介绍PHP无法接收参数的解决方法,并提供具体的代码示例。问题描述在实际
PHP无法接收参数的解决方法详解
2024-03-09

阿里云邮箱接收服务器设置方法详解

阿里云邮箱作为阿里云提供的电子邮件服务,具有强大稳定的特点。对于企业用户来说,如何设置阿里云邮箱接收服务器,是保证邮件正常接收的重要步骤。本文将详细介绍阿里云邮箱接收服务器的设置方法。一、阿里云邮箱接收服务器的设置方法登录阿里云邮箱并进入邮箱设置界面首先,打开阿里云邮箱的网页端或客户端,输入您的邮箱账号和密码进行
阿里云邮箱接收服务器设置方法详解
2023-10-30

[紫色]利用ASP发送和接收XML数据的处理方法284587(思路详解)

因为要做移动梦网WAP的一些接口,所以要用到这种方式,接下来会有ASP.net版本的,这个是ASP版本的,利用了MSXML2.XMLHTTP对像
2023-05-20

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录