Skip to content

Commit 4050917

Browse files
committed
interface done
1 parent abee045 commit 4050917

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

interface.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,88 @@ func Unmarshal(data []byte, v interface{}) error
235235

236236
### 普通类型转换为 iface
237237

238+
```go
239+
1 package main
240+
2
241+
3 import (
242+
4 "io"
243+
5 "os"
244+
6 )
245+
7
246+
8 var j io.Reader
247+
9
248+
10 func main() {
249+
11 var i, _ = os.Open("ab.go")
250+
12 j = i
251+
13 var k = j.(*os.File)
252+
14 println(k)
253+
15 }
254+
```
255+
256+
看看第 12 行的汇编:
257+
258+
```go
259+
0x0050 00080 (interface2.go:12) LEAQ go.itab.*os.File,io.Reader(SB), CX
260+
0x0057 00087 (interface2.go:12) MOVQ CX, "".j(SB)
261+
0x0067 00103 (interface2.go:12) MOVQ AX, "".j+8(SB)
262+
```
263+
264+
和 eface 的赋值其实差不多,稍微有区别的是这里的 go.itab.*os.File,io.Reader(SB),这个符号(理解成一个全局变量,类型是 runtime._type 就行)是编译器帮我们生成的:
265+
266+
```go
267+
go.itab.*os.File,io.Reader SRODATA dupok size=32
268+
0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
269+
0x0010 44 b5 f3 33 00 00 00 00 00 00 00 00 00 00 00 00 D..3............
270+
rel 0+8 t=1 type.io.Reader+0
271+
rel 8+8 t=1 type.*os.File+0
272+
rel 24+8 t=1 os.(*File).Read+0
273+
```
274+
275+
并且是按需生成的,如果你把 `*os.File` 赋值给 io.Writer,在编译结果中也能找到类似的符号:
276+
277+
```go
278+
go.itab.*os.File,io.Writer SRODATA dupok size=32
279+
0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
280+
0x0010 44 b5 f3 33 00 00 00 00 00 00 00 00 00 00 00 00 D..3............
281+
rel 0+8 t=1 type.io.Writer+0
282+
rel 8+8 t=1 type.*os.File+0
283+
rel 24+8 t=1 os.(*File).Write+0
284+
```
285+
286+
看起来就容易理解了。
287+
238288
### iface 转换为普通类型
239289

240-
### 类型转换图
290+
```go
291+
1 package main
292+
2
293+
3 import (
294+
4 "io"
295+
5 "os"
296+
6 )
297+
7
298+
8 var j io.Reader
299+
9
300+
10 func main() {
301+
11 var i, _ = os.Open("ab.go")
302+
12 j = i
303+
13 var k = j.(*os.File)
304+
14 println(k)
305+
15 }
306+
```
307+
308+
主要关心第 13 行的汇编结果:
309+
310+
```go
311+
// 数据准备在这里,AX 和 CX 寄存器 13 行会用到
312+
0x0050 00080 (interface2.go:12) LEAQ go.itab.*os.File,io.Reader(SB), CX
313+
0x0057 00087 (interface2.go:12) MOVQ CX, "".j(SB)
314+
0x0067 00103 (interface2.go:12) MOVQ AX, "".j+8(SB)
315+
316+
0x006e 00110 (interface2.go:13) MOVQ "".j+8(SB), AX // AX = j.data
317+
0x0075 00117 (interface2.go:13) MOVQ "".j(SB), DX // DX = j.itab
318+
0x007c 00124 (interface2.go:13) CMPQ DX, CX // 比较 iface.itab 和 go.itab.*os.File,io.Reader(SB) 是否一致
319+
0x007f 00127 (interface2.go:13) JNE 187 // 不一致,说明断言失败,跳到 panic 流程
320+
321+
// 下面就是正常流程了
322+
```

0 commit comments

Comments
 (0)