Tony Bai · Go 语言第一课
Tony Bai
资深架构师,tonybai.com 博主
21492 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 59 讲
开篇词 (1讲)
结束语 (1讲)
Tony Bai · Go 语言第一课
15
15
1.0x
00:00/00:00
登录|注册

24|方法:理解“方法”的本质

为什么将field类型print方法的receiver类型由*field改为field就可以输出预期的结果了?
输出结果分析
程序修改
问题分析
方法的类型
Method Expression
方法是函数的本质
方法声明的位置约束
receiver参数的作用和限制
方法的声明形式
方法与函数的区别
思考题
巧解难题
方法的本质
基本概念
Go方法

该思维导图由 AI 生成,仅供参考

你好,我是 Tony Bai。
在前面的几讲中,我们对 Go 函数做了一个全面系统的学习。我们知道,函数是 Go 代码中的基本功能逻辑单元,它承载了 Go 程序的所有执行逻辑。可以说,Go 程序的执行流本质上就是在函数调用栈中上下流动,从一个函数到另一个函数
讲到这里,如果你做过提前预习,你可能要站出来反驳我了:“老师,你的说法太过绝对了,Go 语言还有一种语法元素,方法(method),它也可以承载代码逻辑,程序也可以从一个方法流动到另外一个方法”。
别急!我这么说自然有我的道理,等会儿你就知道了。从这节课开始,我们会花三节课的时间,系统讲解 Go 语言中的方法。我们将围绕方法的本质、方法 receiver 的类型选择、方法集合,以及如何实现方法的“继承”这几个主题,进行讲解。
那么,在这一节课中,我就先来解答我们开头提到的这个问题,看看 Go 语言中的方法究竟是什么。等你掌握了方法的本质后,再来评判我的说法是否正确也不迟。

认识 Go 方法

我们知道,Go 语言从设计伊始,就不支持经典的面向对象语法元素,比如类、对象、继承,等等,但 Go 语言仍保留了名为“方法(method)”的语法元素。当然,Go 语言中的方法和面向对象中的方法并不是一样的。Go 引入方法这一元素,并不是要支持面向对象编程范式,而是 Go 践行组合设计哲学的一种实现层面的需要。这个我们后面课程会展开细讲,这里你先了解一下就可以了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Go方法的本质是什么?通过对Go方法的声明形式、约束条件和使用方式的介绍,让读者对Go方法有了初步的了解。方法本质上是一个以方法的receiver参数作为第一个参数的普通函数。文章通过对方法的本质进行深入理解,帮助读者解决实际编码工作中遇到的问题。通过一个实际例子,读者可以了解如何基于对方法本质的深入理解,来分析解决实际编码工作中遇到的真实问题。在“巧解难题”部分,作者通过对问题的分析,解释了为什么只需要将field类型print方法的receiver类型由*field改为field就可以输出预期的结果。通过对Go方法的特点和使用方式的介绍,读者可以更好地理解Go方法的本质和灵活运用。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Tony Bai · Go 语言第一课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(45)

  • 最新
  • 精选
  • ddh
    思考题解答: 由 *field 改为 field结果正确的原因是, *field的方法的第一个参数是*field, 这个对于[]*field数组直接传入成员就可以了, 而对于[]field数组, 则是要取地址,也就是指针。 但是这个指针指的是for range 循环的局部变量的地址, 这个地址在for 循环中是不变的, 在for循环结束后这个地址就指向了最后一个元素, goroutine真正实行打印的解引用的地址是局部变量的地址, 自然只会打印最后一个元素了 field 的方法, 不涉及引用, 传参都是拷贝复制

    作者回复: 👍

    2021-12-08
    3
    54
  • 每天晒白牙
    go方法的本质是一个以方法的 receiver 参数作为第一个参数的普通函数 函数是第一等公民,那大家都写函数就行了,方法存在的意义是啥呢?

    作者回复: 你这个问题很好👍。 我可以将其转换为另外一个几乎等价的问题:我们知道c++的方法(成员函数)本质就是以编译器插入的一个this指针作为首个参数的普通函数。那么大家为什么不直接用c的函数,非要用面向对象的c++呢? 其实你的问题本质上是一个编程范式演进的过程。Go类型+方法(类比于c++的类+方法)和oo范式一样,是一种“封装”概念的实现,即隐藏自身状态,仅提供方法供调用者对其状态进行正确改变操作,防止其他事物对其进行错误的状态改变操作。

    2022-07-15
    2
    18
  • Calvin
    思考题,reciever是 field 值类型非 *field 指针类型,转换后的方法表达式如下: 1) field.print(*v) 2) field.print(v) 打印的都是切片的元素的值。

    作者回复: 👍

    2021-12-08
    2
    16
  • 左耳朵东
    如果 print 方法的 receiver 类型为 field: 首先,两个 for range 循环中的 go v.print() 分别等同于 go field.print(*v) 和 go field.print(v), 然后,第一个 for range 循环,用 *field 去调用 print 方法时,编译器检测到 print 方法只接受 field 值类型参数,所以自动做了隐式类型转换,转成 *v 后传入 print 方法 可以看到两个 for range 中实际传到 print 的实参都是 field 值类型而非指针类型,所以就得到了预期结果

    作者回复: 👍

    2021-12-11
    3
    15
  • 罗杰
    老师在我心目中就是 “Go 语言百科全书”。

    作者回复: 这.... :)

    2021-12-08
    13
  • 进化菌
    *field 改为 field,由指针类型变成普通类型。goroutine在编译的时候就初始化了变量吧,那么指针类型的自然会随着变化而变化,普通类型被值拷贝而不会发生变化。 * 和 & 都是值得花时间学习和理解的东西,不知道老师后面会不会特别的说一下呢?

    作者回复: 指针在Go中被弱化,所以我在设计大纲时没有特意为之留出章节,如果大家有这方面的想法,我和编辑老师看看是否可以在加餐中补充一下。但可能要放在后面了

    2021-12-08
    2
    9
  • aoe
    一直以为 func 开头的就是方法,原来还分函数和方法!我对方法的理解: 1. 提供了良好的封装,receiver 限定了使用对象,方法名可以表使用达对象可以提供的行为 2. 使用起来更方便简洁,因为可以少传一个参数 3. Go 语言设计者的思维真是缜密啊,“方法声明必须与 receiver 参数的基类型在同一个包中”这个规则解决了无数可能出现的奇奇怪怪的情况 4. 可以促进包中代码功能的高内聚,因为你出了包,定义方法时会受到限制,可以及时发现:哎呀,有问题

    作者回复: 👍

    2021-12-10
    2
    6
  • Roway
    *T &T T _ 这四个分别是什么意思?还有哪些基本的概念

    作者回复: T泛指一个go类型 *T 是T类型的指针类型 &T{} 返回一个T类型实例的指针 _ 是go语法中的空标识符

    2022-07-07
    4
  • Geek_7254f2
    建议老师把data1 := []*field{{"one"}, {"two"}, {"three"}}和data2 := []field{{"four"}, {"five"}, {"six"}}其中data1和date2中[]*、[]类型的区别讲一下,就好理解了。特别是还有*[]类型,这三个类型很像,很容易混淆

    作者回复: 好建议👍,感谢。

    2022-02-17
    2
    4
  • Untitled
    receiver 参数的基类型本身不能为指针类型或接口类型?? *T不是指针类型吗?不理解

    作者回复: T是基类型,说的是T本身不能为指针类型。 type T *int func (T) M1() {} // invalid receiver type T (pointer or interface type)

    2022-02-10
    4
收起评论
显示
设置
留言
45
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部