Skip to content

Commit 9e4e4bf

Browse files
committed
update interface
1 parent 7b0057f commit 9e4e4bf

File tree

2 files changed

+87
-4
lines changed

2 files changed

+87
-4
lines changed

generics.md

Whitespace-only changes.

interface.md

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,90 @@
22

33
## iface 和 eface
44

5-
> Written with [StackEdit](https://stackedit.io/).
6-
<!--stackedit_data:
7-
eyJoaXN0b3J5IjpbMTkzNzM1ODI0NV19
8-
-->
5+
Go 使用 iface 和 eface 来表达 interface。iface 其实就是 interface,这种接口内部是有函数的。
6+
7+
eface 表示 empty interface。
8+
9+
非空接口:
10+
```go
11+
// runtime2.go
12+
type iface struct {
13+
tab *itab
14+
data unsafe.Pointer
15+
}
16+
17+
type itab struct {
18+
inter *interfacetype
19+
_type *_type
20+
hash uint32 // copy of _type.hash. Used for type switches.
21+
_ [4]byte
22+
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
23+
}
24+
```
25+
26+
空接口:
27+
28+
```go
29+
type eface struct {
30+
_type *_type
31+
data unsafe.Pointer
32+
}
33+
```
34+
35+
所以我们可以比较容易地推断出来下面两种 interface 在 Go 内部是怎么表示的:
36+
37+
iface:
38+
```go
39+
type Reader interface {
40+
Read([]byte) (int, error)
41+
}
42+
```
43+
44+
eface:
45+
```go
46+
var x interface{}
47+
```
48+
49+
### iface 适用场景
50+
51+
在 Go 语言中,我们可以借助 iface,实现传统 OOP 编程中的 DIP(dependency inversion principle),即依赖反转。
52+
53+
```go
54+
┌─────────────────┐
55+
│ business logic │
56+
└─────────────────┘
57+
58+
59+
60+
┌───────────────────────────────┼───────────────────────────────┐
61+
│ │ │
62+
│ │ │
63+
│ │ │
64+
▼ ▼ ▼
65+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
66+
RPC │ │ DATABASE │ │ CONFIG_SERVICE
67+
└─────────────────┘ └─────────────────┘ └─────────────────┘
68+
```
69+
70+
上面这样的控制流关系在企业软件中很常见,但如果我们让软件的依赖方向与实际控制流方向一致,很容易导致 RPC、CONFIG_SERVER,DATABASE 的抽象被泄露到上层。例如在业务逻辑中有形如下面的结构体定义:
71+
72+
```go
73+
type Person struct {
74+
Age int `db:"age"`
75+
Name string `db:"name"`
76+
}
77+
```
78+
79+
或者在业务逻辑中有类似下面的字眼:
80+
81+
```go
82+
func CreateOrder(order OrderStruct) {
83+
config := GetConfigFromETCD() // abstraction leak
84+
CalcOrderMinusByConfig(config, order)
85+
SaveOrder()
86+
}
87+
```
88+
89+
业务逻辑不应该知道底层的实现,不应该有形如 db 的 tag,不应该知道配置是从 ETCD 中取出的。
90+
91+
### eface 适用场景

0 commit comments

Comments
 (0)