@@ -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