Go中方法接收者是指针类型和值类型的根本区别, 看这一篇就足够了

2024-04-21 05:08

本文主要是介绍Go中方法接收者是指针类型和值类型的根本区别, 看这一篇就足够了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

要理解使用指针接收者和使用值接收者的根本区别只需要明确一点就够了:它们的方法名是不一样的。

方法名

我们拿ManWoman两个简单的结构体举例:

type Man struct {
}
type Woman struct {
}

我们分别使用指针接收者和值接收者给它们添加一个Say()方法:

// Say()方法的全名为(*Man).Say()
// 即只有指针类型*Man才有Say()方法
func (*Man) Say() {
}// Say()方法的全名为(Woman).Say()
// 只有值类型Woman才有Say()方法
func (Woman) Say() {
}

这里虽然它们都是Say()方法,但实际上方法名是不一样的,如果你使用指针接收者,方法的全名为(*Man).Say(), 如果是值类型,则全名为Woman.Say()。严格的来说,对于前者,只能使用(*Man)类型来调用Say()方法,后者则是只能使用Woman类型来调用,因为值类型Man并没有Say()方法,同理指针类型*Woman也没有Say()方法。

编译器隐式转换

那么问题来了,为什么在实际编码时,使用Man.Say()也能通过编译呢?如:

man := Man{} // man是个值类型
man.Say() // ok, 编译器将man隐式转换成了&Man

这是因为go的编译器为了我们做了一次隐式转换,即将man.Say()转换成了(&man).Say(),也就是对man做了取地址操作。同理,如果实参是值类型而形参(方法接收者)是指针类型:

ptrWoman := &Woman{}
ptrWoman.Say() // ok, 编译器将ptrWoman隐式转换成了*Woman

编译器也会为了通过编译而尽量把指针类型ptrWomanWoman类型上"套",这个"套"法就是对ptrWoman做隐式转换,转换成(*ptrWoman).Say(),这样就跟方法名匹配上了。

那么既然编译器这么勤劳,为什么我们还需要关心这个问题呢?原因是对于接口类型,编译器"偷懒"了,并不会主动为我们做类型转换,比如我们定义一个CanTalk接口,里面就有这个Say()方法:

// 定义一个说话接口
type CanTalk interface {// 说话方法Say()
}

这样一来,WomanMan类型应该都实现了这个接口,对吧?其实不然,因为ManSay()方法是指针接收者,所以严格来说是指针类型*Man实现了这个接口,而值类型Man并没有。同理,因为WomanSay()方法是值类型,所以严格来说是Woman实现了这个接口,而*Woman则没有。所以,如果你把值类型Man的变量赋值给接口CanTalk是会报错的:

	var canTalk CanTalkcanTalk = man // error, Man类型没有Say()方法// cannot use man (type Man) as type CanTalk in assignment:// Man does not implement CanTalk (Say method has pointer receiver)

而反过来,如果将指针类型*Man的变量赋值给CanTalk则没有问题:

canTalk = ptrMan // ok, *Man类型有Say()方法

妈妈再也不用担心我搞不清楚指针类型和值类型接收者的区别了!

这篇关于Go中方法接收者是指针类型和值类型的根本区别, 看这一篇就足够了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/922215

相关文章

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0