1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 20:52:22 +00:00

update if

This commit is contained in:
Xargin 2018-06-18 20:48:01 +08:00
parent 6d3620c6c2
commit 221bcf6757

View File

@ -156,7 +156,7 @@ func BusinessProcess(bi BusinessInstance) {
直接面向 interface 编程,而不用关心具体的实现了。如果对应的业务在迭代中发生了修改,所有的逻辑对平台方来说也是完全透明的。 直接面向 interface 编程,而不用关心具体的实现了。如果对应的业务在迭代中发生了修改,所有的逻辑对平台方来说也是完全透明的。
## interface 是必须的吗? ## interface 的优缺点
Go 被人称道的最多的地方是其 interface 设计的正交性模块之间不需要知晓相互的存在A 模块定义 interfaceB 模块实现这个 interface 就可以。如果 interface 中没有 A 模块中定义的数据类型,那 B 模块中甚至都不用 import A。比如标准库中的 `io.Writer` Go 被人称道的最多的地方是其 interface 设计的正交性模块之间不需要知晓相互的存在A 模块定义 interfaceB 模块实现这个 interface 就可以。如果 interface 中没有 A 模块中定义的数据类型,那 B 模块中甚至都不用 import A。比如标准库中的 `io.Writer`
@ -200,15 +200,20 @@ func init() {
在 MyType 定义的地方,不需要 `import "io"` 就可以直接实现 `io.Writer` interface我们还可以随意地组合很多函数以实现各种类型的接口同时接口实现方和接口定义方都不用建立 import 产生的依赖关系。因此很多人认为 Go 的这种正交是一种很优秀的设计。 在 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 ```go
TODO
``` ```
## 要不要用继承? ## 要不要用继承?
既然谈到了 interface那就免不了要提到继承的问题。有很多 java 和 C# 来的程序员对于 Go 没有继承非常的不习惯。继承也是为了实现抽象,把复杂模块中的公共逻辑向上抽离至抽象类,以达到代码共用的目的。所以说到面向对象,大多数程序员脑子里第一反应就是:"封装、继承、多态"。封装和多态自不用说,而继承在 Go 里与传统的 OOP 语言里差别非常之大,甚至有人觉得已经差异到了令人发指的程度,比如下面的例子:
TODO继承是正确的设计模式么
## table-driven 开发 ## table-driven 开发
熟悉开源 lint 工具的同学应该见到过圈复杂度的说法,在函数中如果有 if 和 switch 的话,会使函数的圈复杂度上升,所以有强迫症的同学即使在入口一个函数中有 switch还是想要干掉这个 switch有没有什么办法呢当然有用表驱动的方式来存储我们需要实例 熟悉开源 lint 工具的同学应该见到过圈复杂度的说法,在函数中如果有 if 和 switch 的话,会使函数的圈复杂度上升,所以有强迫症的同学即使在入口一个函数中有 switch还是想要干掉这个 switch有没有什么办法呢当然有用表驱动的方式来存储我们需要实例