城市旅游网

>> 您当前的位置: 首页 -> 网站

Golang接收者方法语法糖

时间:2023-05-16 20:42:06 来源:博客园
1、概述

在《Golang常用语法糖》这篇博文中我们讲解Golang中常用的12种语法糖,在本文我们主要讲解下接收者方法语法糖。

在介绍Golang接收者方法语法糖前,先简单说下Go 语言的指针 (Pointer),大致上理解如下:


【资料图】

变量名前的 &符号,是取变量的内存地址,不是取值;数据类型前的 *符号,代表要储存的是对应数据类型的内存地址,不是存值;变量名前的 *符号,代表从内存地址中取值 (Dereferencing)。

注意 1:golang 指针详细介绍请参见《Golang指针隐式间接引用》此篇博文。

2、接收者方法语法糖

在 Go 中,对于自定义类型 T,为它定义方法时,其接收者可以是类型 T 本身,也可能是 T 类型的指针 *T。

type Instance struct{}func (ins *Instance) Foo() string { return ""}

在上例中,我们定义了 Instance 的 Foo 方法时,其接收者是一个指针类型(*Instance)。

func main() { var _ = Instance{}.Foo() //编译错误:cannot call pointer method on Instance{} ,变量是不可变的(该变量没有地址,不能对其进行寻址操作)}

因此,如果我们用 Instance 类型本身 Instance{} 值去调用 Foo 方法,将会得到以上错误。

type Instance struct{}func (ins Instance) Foo() string { return ""}func main() { var _ = Instance{}.Foo() // 编译通过}

此时,如果我们将 Foo 方法的接收者改为 Instance 类型,就没有问题。

这说明,定义类型 T 的函数方法时,其接收者类型决定了之后什么样的类型对象能去调用该函数方法。但,实际上真的是这样吗?

type Instance struct{}func (ins *Instance) String() string { return ""}func main() { var ins Instance _ = ins.String() // 编译器会自动获取 ins的地址并将其转换为指向 Instance类型的指针_ = (&ins).String()}

实际上,即使是我们在实现 Foo 方法时的接收者是指针类型,上面 ins 调用的使用依然没有问题。

Ins 值属于 Instance 类型,而非 *Instance,却能调用 Foo 方法,这是为什么呢?这其实就是 Go 编译器提供的语法糖!

当一个变量可变时(也就是说,该变量是一个具有地址的变量,我们可以对其进行寻址操作),我们对类型 T 的变量直接调用 *T 方法是合法的,因为 Go 编译器隐式地获取了它的地址。变量可变意味着变量可寻址,因此,上文提到的Instance{}.Foo()会得到编译错误,就在于 Instance{} 值不能寻址。

注意 1:在 Go 中,即使变量没有被显式初始化,编译器仍会为其分配内存空间,因此变量仍然具有内存地址。不过,由于变量没有被初始化,它们在分配后仅被赋予其类型的默认零值,而不是初始值。当然,这些默认值也是存储在变量分配的内存空间中的。

例如,下面的代码定义了一个整型变量 x,它没有被显式初始化,但是在分配内存时仍然具有一个地址:

var x intfmt.Printf("%p\n", &x) // 输出变量 x 的内存地址

输出结果类似于:0xc0000120a0,表明变量 x的内存地址已经被分配了。但是由于变量没有被初始化,x的值将为整型的默认值 0。  

3、深入测试3.1 示例
package maintype B struct {    Id int}func New() B {    return B{}}func New2() *B {    return &B{}}func (b *B) Hello() {    return}func (b B) World() {    return}func main() {    // 方法的接收器为 *T 类型    New().Hello() // 编译不通过    b1 := New()    b1.Hello() // 编译通过    b2 := B{}    b2.Hello() // 编译通过    (B{}).Hello() // 编译不通过    B{}.Hello()   // 编译不通过    New2().Hello() // 编译通过    b3 := New2()    b3.Hello() // 编译通过    b4 := &B{} // 编译通过    b4.Hello() // 编译通过    (&B{}).Hello() // 编译通过    // 方法的接收器为 T 类型    New().World() // 编译通过    b5 := New()    b5.World() // 编译通过    b6 := B{}    b6.World() // 编译通过    (B{}).World() // 编译通过    B{}.World()   // 编译通过    New2().World() // 编译通过    b7 := New2()    b7.World() // 编译通过    b8 := &B{} // 编译通过    b8.World() // 编译通过    (&B{}).World() // 编译通过}

输出结果:

./main.go:25:10: cannot call pointer method on New()./main.go:25:10: cannot take the address of New()./main.go:33:10: cannot call pointer method on B literal./main.go:33:10: cannot take the address of B literal./main.go:34:8: cannot call pointer method on B literal./main.go:34:8: cannot take the address of B literal
3.2 问题总结假设T类型的方法上接收器既有T类型的,又有*T指针类型的,那么就不可以在不能寻址的T值上调用*T接收器的方法&B{}是指针,可寻址B{}是值,不可寻址b := B{}b是变量,可寻址4、总结

在 Golang 中,当一个变量是可变的(也就是说,该变量是一个具有地址的变量,我们可以对其进行寻址操作),我们可以通过对该变量的指针进行方法调用来执行对该变量的操作,否则就会导致编译错误。

参考:Go 中的那些语法糖

参考:Go 挖坑指南: cannot take the address & cannot call pointer method

关键词:
关注:艾芬达电热毛巾架开启618狂欢 与消费者展开双向奔赴

一年一度的618年中大促已经拉开序幕,作为疫情防控政策调整后首个大型购物节,备受各方关注和期待。各大电

教育部:2023年全国高考报名人数1291万人 再创历史新高

【教育部:2023年全国高考报名人数1291万人再创历史新高】财联社6月1日电,教育部网站消息,2023年全国高考报名

沪深股通|铜陵有色5月31日获外资卖出0.11%股份

同花顺数据显示,2023年5月31日,铜陵有色获外资卖出1128 0万股,占流通盘0 11%。截至目前,陆股通持有铜陵

中指研究院:5月百城新房价格止涨转跌 二手房跌幅扩大

中指研究院消息,2023年5月,百城新建住宅平均价格为16180元 平方米,环比止涨转跌,跌幅为0 01%;同比跌幅

每日热议!剑网3职业定位解析(剑网3全职业强弱定位分析)

剑网3什么职业好玩?很多刚入门的萌新不知道怎么选择职业,下面小编给大家带来了关于剑网3职业定位解析,一

天天观焦点:手机怎么申请微信号码(怎么申请微信号码)

1、不用申请。2、直接用QQ号上就可以了。本文到此分享完毕,希望对大家有所帮助。

环球实时:技能人员职业资格证书有哪些_职业资格证书有哪些

1、全国职业资格证书分为五大类:劳动部证书、人事部证书、建设部证书、旅游局证书、财政部证书。2、国家级

醉酒驾车撞伤人怎么处罚?

其实,在道路上驾驶机动车,血液酒精含量达到80毫克 100毫升以上的,属于醉酒驾驶机动车,涉嫌危险驾驶罪定

财神客栈演员表十八铜人(财神客栈演员表) 天天观察

关于财神客栈演员表十八铜人,财神客栈演员表这个很多人还不知道,现在让我们一起来看看吧!1、《财神

深交所向神农科技发出问询函-天天新消息

2023年5月31日,深交所向神农科技(SZ300189,收盘价:3 2元)发出问询函:针对“2020年至2022年,你公司分

全球实时:湖南机电职院经济贸易学院赴湘潭九华经开区访企拓岗 落实就业岗位80余个

为贯彻落实教育部2023年高校书记校长“访企拓岗促就业”专项行动要求,深化校企合作,推进校企共建产业...

广发证券(01776.HK)拟发行不超50亿元永续次级债券_环球焦点

投行对该股的评级以买入为主,近90天内共有3家投行给出买入评级,近90天的目标均价为14 61港元。证券之星力

“交子新月”主体 成都锦尚大桥钢箱拱提前180天合龙

5月31日,随着最后一片长6 8米,宽4 1米,重38吨的钢箱拱H节段吊装到位,位于四川省成都市交子公园金融商务

新华社权威快报丨婚姻登记“跨省通办”需选择经常居住地,可提前预约 天天观热点

6月1日起,北京、天津、河北、内蒙古、辽宁、上海、江苏、浙江、安徽、福建、江西、山东、河南、湖北、广东

当科技体验活动走进社区,会碰撞出哪些火花? 全球快报

你见过AI机器人跳《小苹果》吗?为什么在手上放一把火却不会烧伤?零下78 5℃的干冰是怎么制作出云海效果的

金田股份: 金田股份关于向不特定对象发行可转换公司债券申请获得上海证券交易所上市审核委员会审议通过的公告

金田股份:金田股份关于向不特定对象发行可转换公司债券申请获得上海证券交易所上市审核委员会审议通过的公

中信博(688408)5月31日主力资金净买入1348.80万元 全球快报

截至2023年5月31日收盘,中信博(688408)报收于75 8元,上涨0 66%,换手率4 09%,成交量2 99万手,成交额2 25亿元。

世界热文:世界无烟日 自由呼吸,拒绝香烟

世界无烟日自由呼吸,拒绝香烟(主题)钱江晚报记者孙燕5月31日是世界无烟日。在国家卫生健康委发布的《中

【环球聚看点】久远银海5月31日盘中涨停

以下是久远银海在北京时间5月31日14:40分盘口异动快照:5月31日14点40分,久远银海盘中涨停,报31 19元,目

美国财政部以参与跨国销售非法药品生产设备为由,宣布制裁13个中国实体与个人,中国驻美国大使馆回应_当前速看

美方实施此次制裁的借口是这些中国实体和个人向美国和墨西哥销售压片机、模具等设备。在国际社会和中国芬太

618这张牌怎么打?魅族20系列绝杀:我出“3年质保”-世界报资讯

在新机浪潮汹涌、降价无处不在的618,如何让自家旗舰机型脱颖而出?有的邀请代言人助阵,有的则展开广告攻

制造一架C919大飞机到底有多复杂?民航专家解读来了

制造一架C919大飞机到底有多复杂?民航专家解读来了,空客,波音,邹建军,民航专家,全生命周期,中国军工企业,c

x 广告
x 广告