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

30|接口:Go中最强大的魔法

你好,我是 Tony Bai。
在前面的两讲中,我们学习了接口的基础知识、接口类型定义的惯例以及接口在运行时的表示。掌握了这些内容后,可以说,在语法层面的有关接口的问题,对我们来说都不是什么阻碍了。在弄清楚接口是什么这个问题之后,摆在我们面前的就是怎么用接口的问题了。
不过,这里的“怎么用”,可不是要告诉你怎么使用 Go 标准库中的接口或第三方包中定义好的接口,而是让你学习如何利用接口进行应用的设计,以及改善已有应用的设计,换句话说就是 Go 接口的应用模式或惯例
不过在讲解接口应用模式之前,我们还先要了解一个前置原则,那就是在实际真正需要的时候才对程序进行抽象。再通俗一些来讲,就是不要为了抽象而抽象。上一讲中我们说过,接口本质上是一种抽象,它的功能是解耦,所以这条原则也在告诉我们:不要为了使用接口而使用接口。举一个简单的例子,如果我们要给一个计算器添加一个整数加法的功能特性,本来一个函数就可以实现:
func Add(a int64, b int64) int64 {
return a+b
}
但如果你非要引入一个接口,结果代码可能就变成了这样:
type Adder interface {
Add(int64, int64) int64
}
func Add(adder Adder, a int64, b int64) int64 {
return adder.Add(a, b)
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Tony Bai · Go 语言第一课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(30)

  • 最新
  • 精选
  • return
    老师讲的太好了,虽然定位是入门, 但个人认为, 基础才是最核心的, 老师把基础讲的太透彻了。这个专栏比某些进阶高阶专栏好多了。 这一篇 加深了 我对组合的理解, 感谢老师用心的输出。 好饭不怕晚, 耐心等等老师后续的 高质量知识, 大家别催,品质第一。

    作者回复: 👍

    29
  • Geek_2337af
    在学习上遇到一个问题,请老师解答: IntSet类型的String方法的接收者是一个指针类型,所以我们不能在一个不能寻址的IntSet值上调用这个方法 type IntSet struct { /* ... */ } func (*IntSet) String() string var _ = IntSet{}.String() // compile error: String requires *IntSet receiver 但是我们可以在一个IntSet值上调用这个方法: var s IntSet var _ = s.String() // OK: s is a variable and &s has a String method 1.怎么理解这个不能寻址的IntSet值 2.调用方法的习惯是直接使用结构体变量(var i InSet),还是j := InSet{},假设方法中不需要使用到这个实例

    作者回复: 好问题!👍 1. go规范中说: 只有可寻址的(addressable)的变量在调用*T作为receiver参数类型的方法时,Go才会施展“语法糖”,取其地址再调用对应的方法。关于addressable这个概念比较复杂,在专栏里不便展开,就没有提。var _ = IntSet{}.String() 中的IntSet()是一个中间值,是不可获得其地址的,因此不能被自动转换,因此编译器报错。 2. 调用方法的习惯没有标准😁

    2
    10
  • 文经
    白老师,这段代码我有点疑问: type HandlerFunc func(ResponseWriter, *Request) 这里是定义了HandlerFunc类型 http.HandlerFunc(greetings) 在这里是不是对greetings做了类型转换?像是int64(123)。我把这个跟对象的初始化有点混淆,觉得要有个字段来存储greetings的值。

    作者回复: 你的理解没错!这个在专栏前面的课程中也讲过,这里就是一个类型转换。通过类型转换,HandlerFunc可以让一个普通函数成为实现ServeHTTP方法的对象,从而满足http.Handler接口。

    2
    7
  • aoe
    Go 中的接口实现的是真里氏替换原则(LSP),再也不用担心父类强转子类后使用子类特有方法的假里氏替换原则了

    作者回复: 👍

    7
    7
  • SuperSu
    先生循循善诱,看的学生直呼过瘾

    作者回复: 👍

    归属地:辽宁
    4
  • 多选参数
    特别喜欢白老师讲 Go,这个专栏虽然说是 Go 第一课,但是感觉这内容已经不是基础的内容,而是作为深度入门 Go 的课了。另外,整篇专栏中,老师始终在不断给我讲 Go 的思想,这点真的超 nice。原本我觉得用一门要用它特有的东西,比如 Go 的并发,而白老师让我更深入去理解 Go 的思想,这才是活用一门语言的样子。

    作者回复: 👍

    4
  • 文经
    强烈请求白老师做一次加餐:讲一讲自己的Go语言学习之路,以及自己怎么做到写出来的文章即通俗易懂又足够深入的👍这种能力能学习不?

    作者回复: 我自己的学习之路,我还真没有“认真”总结过。手动允悲:)。

    3
  • Calvin
    Gopher 这里说的“中间件”和 PHPer 的“中间件”概念是不是有点像? 但是貌似跟 Javaer 的“中间件”概念不太一样:Javaer 的“中间件”是类似 kafka、zookeeper 等之类的软件项目,而 Gopher 的“中间件”感觉更像是 Javaer 中的“过滤器”、“拦截器”概念?

    作者回复: 你说的没错。中间件(middleware)这个词的具体含义要结合具体上下文来看。

    3
  • Geek_73c432
    type MyError struct { err error } func (e MyError) Error() string { return "fatal error" } func NewError(e error) *MyError { var p *MyError p = &MyError{err: e} return p } 在创建者模式中,我看到创建函数的惯例是返回结构的指针,例如变量 p,但是函数调用后变量 p 所在的栈帧已经被回收了啊,那外部的指针 q := NewError(e) 指向的地址不是无效了么?

    作者回复: Go编译器会对各个变量做逃逸分析(escape analysis),对于逃逸的变量,go编译器会将其分配在heap上,这样return 的p在函数NewError外面使用也是安全有效的。

    归属地:广东
    2
  • pyhhou
    尝试着去理解 logHandler(authHandler(http.HandlerFunc(greetings)))() 的执行过程,像是 logHandler 以及 authHandler 这种中间件函数都会返回一个闭包函数,在闭包函数中它们通过 h.ServeHTTP(w, r) 与下一层的(传入的)函数进行链接 ServeHTTP 设计的挺巧妙的,仅仅看这个函数的定义并不太理解,看了例子后才明白其用意 不知道我理解的对不对,或者哪里有遗漏,还望老师指教 🙏

    作者回复: ✅

    2
    2
收起评论
显示
设置
留言
30
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部