学习疑惑: Golang 中接口的作用体现在哪里?

2018-09-28 16:56:46 +08:00
 Deardrops

初学 Golang,对于接口部分有一些不太理解的地方,希望 V 友能帮忙解答一下。

package main

import "fmt"

type Stringer interface {
	String() string
}

type Printer interface {
	Stringer // 接口嵌入。
	Print()
}

type User struct {
	id   int
	name string
}

func (self *User) String() string {
	return fmt.Sprintf("user %d, %s", self.id, self.name)
}

func (self *User) Print() {
	fmt.Println(self.String())
}

func main() {
	var t Printer = &User{1, "Tom"} // *User 方法集包含 String、Print。
	// 如果去掉接口定义的代码,将上一行代码替换为下行,也可以运行,请问接口的作用体现在哪里?
	// var t := User{1, "Tom"}
	t.Print()
}

以上代码摘录自Go 边看边练 -《 Go 学习笔记》系列(十二)

书上写了接口声明一个方法的签名。声明一个空方法集的接口类型,并将其作为函数参数,函数不会检查传入的是什么类型,只要这个参数满足接口定义即可,即可以通过编译器检查(个人理解)。另外,接口可以进行接口检查,接口嵌入等。我学到了这些理论知识,但对接口缺乏感性的认识。

相对于不定义接口,「直接定义结构体和结构体上的方法」的方式,额外定义了接口会带来什么好处么?

可以举几个实际的例子么?

6504 次点击
所在节点    Go 编程语言
11 条回复
gowk
2018-09-28 17:12:15 +08:00
接口跟语言无关,无非是为了抽象,具体说就是为了解耦,隔离变化。Go 语言中的接口跟 Java 中的大同小异,最大的区别就是 Go 语言的 Interface 是 Duck Typing,无侵入式的,另外我建议你不要用这个教程学习 Go 语言,教程里的例子为了举例而举例,对初学者而言完全没有任何意义。英文好的话直接看英文教程,推荐两本书,《 The Go Programming Language 》《 The Way To Go 》,英语对于程序员的重要性再怎么强调都不为过!
gowk
2018-09-28 17:15:44 +08:00
上面两本电子书找不到的话,可以访问我的百度网盘分享链接: https://pan.baidu.com/s/1mic0v00
里面有很多经典的计算机类的 PDF 电子书
imnotfine
2018-09-28 17:20:25 +08:00
其实面向对象的问题.

如果你初学编程的话, 我非常建议你跳过这部分, 因为需要你做一些项目才能理解其作用 ,特别是需要多人合作的项目

------

举个栗子, 如果你写了一个类, 一年后你对这个类不满意, 你想重新实现一个, 那为了保证兼容性, 你肯定不能完全写个新的对吧.

那你肯定要理清这个类提供了哪些公开的 api, 那你就得到了一个接口

然后根据这些 api 去实现一个新的类, 然后用这个新的类去替换旧代码.

-------

下面是更好的方案

那其实更好的方式是, 在刚开始写这个类的时候就想好这个类可以提供哪些方法, 然后定义一个接口, 然后一年后你写个新的, 你直接实现这个接口就好了, 而不用理清. 另外, 试想, 如果写这个新类的人是你同事, 让他去理清这些公开 api, 他应该会很头疼, 甚至直接放弃这个需求了吧.

------

除了修改和重构上的方便外, 对调用方来说也是非常重要的, 这个涉及到多态, 然后你联想一下设计模式, 还有为什么允许`var t Printer = &User{1, "Tom"}`, 甚至推荐这种用法, 这就是你要思考的问题啦~
Deardrops
2018-09-28 17:23:20 +08:00
@gowk #1 感谢解答。正在看这两本书,看到接口的部分看不大明白,谷歌到的一个解释接口的文章,顺手贴出来了。书中说,Golang 语言中接口和满足接口的类型之间没有显式的连接,有时有的自定义类型可以同时满足多个接口,使用起来不会带来困惑么?
neoblackcap
2018-09-28 17:27:24 +08:00
@Deardrops 这就是语言的哲学,也是面向对象的进一步理解。面向对象应该基于协议,接口。组合优先于继承,既然满足了接口,那么就应该认为这里的对象就是一类。
Deardrops
2018-09-28 17:28:49 +08:00
@imnotfine #3 感谢解答。之前写过一些 JS,对 OOP 一直没啥概念,听了你的解释明白了很多东西。谢谢!
tourist2018
2018-09-28 17:38:15 +08:00
golang 的接口就是一系列方法的集合
misaka19000
2018-09-28 17:44:51 +08:00
我也是在了解了 golang 的接口之后才对计算机里面的指令和数据有了更进一步的了解
gamexg
2018-09-28 20:58:03 +08:00
实际使用下 go 的压缩、加密库就能够理解接口的作用了。
加密、压缩传入 Writer 接口,输出的还是兼容 Writer,只要需求方实现了 Write 方法都能使用,不用管是文件还是连接。
owenliang
2018-09-29 09:52:39 +08:00
面向接口编程啊,无论是过程式的还是对象式的,都可以实现接口和实现的分离。
hijoker
2018-09-30 14:11:57 +08:00
感觉卵用没有,没有默认的接口实现

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/493568

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX