《the way to go》一处关于go匿名函数的“勘误”
生活随笔
收集整理的這篇文章主要介紹了
《the way to go》一处关于go匿名函数的“勘误”
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
《the way to go》是go的一門經典入門書籍,但是由于書的編纂比較早,有些知識點已經過時了。
在6.8章節中有這么一處代碼,
package mainimport "fmt"func main() {f() } func f() {for i := 0; i < 4; i++ {g := func(i int) { fmt.Printf("%d", i) }g(i)fmt.Printf(" - g is of type %T and has value %v\n", g, g)} }輸出
0 - g is of type func(int) and has value 0x681a80 1 - g is of type func(int) and has value 0x681b00 2 - g is of type func(int) and has value 0x681ac0 3 - g is of type func(int) and has value 0x681400但是,當你自己去運行這個代碼的時候,你就發現,輸出四次的函數內存地址是一樣的,這里我們寫一個簡易的代碼,然后把它轉成匯編,看一下
package mainfunc main() {for i := 0; i < 4; i++ {g := func() {}_ = g} }執行命令
go tool compile -S main.go得到匯編代碼
"".main t=1 size=18 args=0x0 locals=0x00x0000 00000 (main.go:3) TEXT "".main(SB), $0-00x0000 00000 (main.go:3) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:3) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:4) MOVQ $0, AX0x0002 00002 (main.go:4) CMPQ AX, $40x0006 00006 (main.go:4) JGE $0, 170x0008 00008 (main.go:4) INCQ AX0x000b 00011 (main.go:4) CMPQ AX, $40x000f 00015 (main.go:4) JLT $0, 80x0011 00017 (main.go:8) RET0x0000 31 c0 48 83 f8 04 7d 09 48 ff c0 48 83 f8 04 7c 1.H...}.H..H...|0x0010 f7 c3 .. "".main.func1 t=1 size=1 args=0x0 locals=0x00x0000 00000 (main.go:5) TEXT "".main.func1(SB), $0-00x0000 00000 (main.go:5) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:5) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:5) RET0x0000 c3 . "".init t=1 size=79 args=0x0 locals=0x80x0000 00000 (main.go:9) TEXT "".init(SB), $8-00x0000 00000 (main.go:9) MOVQ (TLS), CX0x0009 00009 (main.go:9) CMPQ SP, 16(CX)0x000d 00013 (main.go:9) JLS 720x000f 00015 (main.go:9) SUBQ $8, SP0x0013 00019 (main.go:9) MOVQ BP, (SP)0x0017 00023 (main.go:9) LEAQ (SP), BP0x001b 00027 (main.go:9) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x001b 00027 (main.go:9) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x001b 00027 (main.go:9) MOVBLZX "".initdone·(SB), AX0x0022 00034 (main.go:9) CMPB AL, $10x0024 00036 (main.go:9) JLS $0, 470x0026 00038 (main.go:9) MOVQ (SP), BP0x002a 00042 (main.go:9) ADDQ $8, SP0x002e 00046 (main.go:9) RET0x002f 00047 (main.go:9) JNE $0, 560x0031 00049 (main.go:9) PCDATA $0, $00x0031 00049 (main.go:9) CALL runtime.throwinit(SB)0x0036 00054 (main.go:9) UNDEF0x0038 00056 (main.go:9) MOVB $2, "".initdone·(SB)0x003f 00063 (main.go:9) MOVQ (SP), BP0x0043 00067 (main.go:9) ADDQ $8, SP0x0047 00071 (main.go:9) RET0x0048 00072 (main.go:9) NOP0x0048 00072 (main.go:9) PCDATA $0, $-10x0048 00072 (main.go:9) CALL runtime.morestack_noctxt(SB)0x004d 00077 (main.go:9) JMP 00x0000 65 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 39 48 eH..%....H;a.v9H0x0010 83 ec 08 48 89 2c 24 48 8d 2c 24 0f b6 05 00 00 ...H.,$H.,$.....0x0020 00 00 3c 01 76 09 48 8b 2c 24 48 83 c4 08 c3 75 ..<.v.H.,$H....u0x0030 07 e8 00 00 00 00 0f 0b c6 05 00 00 00 00 02 48 ...............H0x0040 8b 2c 24 48 83 c4 08 c3 e8 00 00 00 00 eb b1 .,$H...........rel 5+4 t=16 TLS+0rel 30+4 t=15 "".initdone·+0rel 50+4 t=8 runtime.throwinit+0rel 58+4 t=15 "".initdone·+-1rel 73+4 t=8 runtime.morestack_noctxt+0 gclocals·33cdeccccebe80329f1fdbee7f5874cb t=8 dupok size=80x0000 01 00 00 00 00 00 00 00 ........ go.info."".main t=45 size=270x0000 02 22 22 2e 6d 61 69 6e 00 00 00 00 00 00 00 00 ."".main........0x0010 00 00 00 00 00 00 00 00 00 01 00 ...........rel 9+8 t=1 "".main+0rel 17+8 t=1 "".main+18 go.info."".main.func1 t=45 size=330x0000 02 22 22 2e 6d 61 69 6e 2e 66 75 6e 63 31 00 00 ."".main.func1..0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................0x0020 00 .rel 15+8 t=1 "".main.func1+0rel 23+8 t=1 "".main.func1+1 go.info."".init t=45 size=270x0000 02 22 22 2e 69 6e 69 74 00 00 00 00 00 00 00 00 ."".init........0x0010 00 00 00 00 00 00 00 00 00 01 00 ...........rel 9+8 t=1 "".init+0rel 17+8 t=1 "".init+79 "".initdone· t=32 size=1 "".main.func1·f t=8 dupok size=80x0000 00 00 00 00 00 00 00 00 ........rel 0+8 t=1 "".main.func1+0請注意這里
"".main.func1 t=1 size=1 args=0x0 locals=0x00x0000 00000 (main.go:5) TEXT "".main.func1(SB), $0-00x0000 00000 (main.go:5) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:5) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (main.go:5) RET0x0000 c3這里就是生成匿名函數的匯編代碼,可以看到,整個代碼只生成一次匿名函數。
我測試了1.2-1.8版本,都是一樣的。
個人推測,《the way to go》編寫的2012的時候,go1.0剛剛發布,編譯器并沒有對這種代碼做優化,所以出現了書中描述的現象,
更多架構、PHP、GO相關踩坑實踐技巧請關注我的公眾號:PHP架構師
轉載于:https://my.oschina.net/u/222608/blog/1073901
總結
以上是生活随笔為你收集整理的《the way to go》一处关于go匿名函数的“勘误”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个人买生育保险怎么买 个人如何买生育保险
- 下一篇: 刚买了三者没买不计免赔怎么办 刚买了三者