mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 12:32:21 +00:00
update if
This commit is contained in:
parent
6d3620c6c2
commit
221bcf6757
@ -156,7 +156,7 @@ func BusinessProcess(bi BusinessInstance) {
|
||||
|
||||
直接面向 interface 编程,而不用关心具体的实现了。如果对应的业务在迭代中发生了修改,所有的逻辑对平台方来说也是完全透明的。
|
||||
|
||||
## interface 是必须的吗?
|
||||
## interface 的优缺点
|
||||
|
||||
Go 被人称道的最多的地方是其 interface 设计的正交性,模块之间不需要知晓相互的存在,A 模块定义 interface,B 模块实现这个 interface 就可以。如果 interface 中没有 A 模块中定义的数据类型,那 B 模块中甚至都不用 import A。比如标准库中的 `io.Writer`:
|
||||
|
||||
@ -200,15 +200,20 @@ func init() {
|
||||
|
||||
在 MyType 定义的地方,不需要 `import "io"` 就可以直接实现 `io.Writer` interface,我们还可以随意地组合很多函数,以实现各种类型的接口,同时接口实现方和接口定义方都不用建立 import 产生的依赖关系。因此很多人认为 Go 的这种正交是一种很优秀的设计。
|
||||
|
||||
但这种“正交”性也会给我们带来一些麻烦。当我们接手了一个几十万行的系统时,如果看到定义了很多 interface,例如订单流程的 interface,我们希望能直接找到这些 interface 都被哪些对象实现了。但直到现在,这个简单的需求也就只有 goland 实现了,并且体验尚可。Visual Studio Code 则需要对项目进行全局扫描,来看到底有哪些 struct 实现了所有该 interface 的函数。对于那些显式实现 interface 的语言来说,对于 IDE 的 interface 实现查找来说就友好多了。另一方面,我们看到一个 struct,也希望能够立刻知道这个 struct 实现了哪些 interface,但也有着和前面提到的相同的问题。
|
||||
但这种“正交”性也会给我们带来一些麻烦。当我们接手了一个几十万行的系统时,如果看到定义了很多 interface,例如订单流程的 interface,我们希望能直接找到这些 interface 都被哪些对象实现了。但直到现在,这个简单的需求也就只有 goland 实现了,并且体验尚可。Visual Studio Code 则需要对项目进行全局扫描,来看到底有哪些 struct 实现了该 interface 的全部函数。那些显式实现 interface 的语言,对于 IDE 的 interface 查找来说就友好多了。另一方面,我们看到一个 struct,也希望能够立刻知道这个 struct 实现了哪些 interface,但也有着和前面提到的相同的问题。
|
||||
|
||||
如果我们只是为了规定一个业务组件需要实现哪些功能的话,必须用 interface 么?显然不是必须的:
|
||||
interface 本身的意义在哪里呢?一是依赖反转,在 Go 的正交 interface 的设计场景下甚至可以去除依赖;二是由编译器来帮助我们在编译期就能检查到类似“未完全实现接口”这样的错误,如果业务未实现某个流程,但又将其实例作为 interface 强行传给我们的初始化函数,就会报出下面的错误:
|
||||
|
||||
```go
|
||||
TODO
|
||||
```
|
||||
|
||||
## 要不要用继承?
|
||||
|
||||
既然谈到了 interface,那就免不了要提到继承的问题。有很多 java 和 C# 来的程序员对于 Go 没有继承非常的不习惯。继承也是为了实现抽象,把复杂模块中的公共逻辑向上抽离至抽象类,以达到代码共用的目的。所以说到面向对象,大多数程序员脑子里第一反应就是:"封装、继承、多态"。封装和多态自不用说,而继承在 Go 里与传统的 OOP 语言里差别非常之大,甚至有人觉得已经差异到了令人发指的程度,比如下面的例子:
|
||||
|
||||
TODO,继承是正确的设计模式么?
|
||||
|
||||
## table-driven 开发
|
||||
|
||||
熟悉开源 lint 工具的同学应该见到过圈复杂度的说法,在函数中如果有 if 和 switch 的话,会使函数的圈复杂度上升,所以有强迫症的同学即使在入口一个函数中有 switch,还是想要干掉这个 switch,有没有什么办法呢?当然有,用表驱动的方式来存储我们需要实例:
|
||||
|
Loading…
x
Reference in New Issue
Block a user