原本想写一篇关于defer的常用和底层调用逻辑,然后发现其实自己目前还没能力。
推荐两篇文,再列一下自己的一些小demo & 执行结果 & 反汇编过程。
一、推荐的文章
煎鱼大佬的深入理解Go defer https://eddycjy.com/posts/go/defer/2019-05-27-defer/
真迹大佬的 https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-defer/
golang内存分配逃逸分析 https://driverzhang.github.io/post/golang%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E9%80%83%E9%80%B8%E5%88%86%E6%9E%90/
Golang 混合写屏障原理深入剖析 https://www.huaweicloud.com/articles/9aa423940e224bc6ff57a0c63e2615fa.html
Golang的垃圾回收与三色标记法 http://austsxk.com/2020/12/07/Golang-GC%20%E4%B8%89%E8%89%B2%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E6%B7%B7%E5%90%88%E8%AF%BB%E5%86%99%E5%B1%8F%E9%9A%9C/
Golang三色标记、混合写屏障GC模式图文全分析 https://segmentfault.com/a/1190000022030353
Golang 内存管理 https://zhuanlan.zhihu.com/p/27807169
贴图来自:https://my.oschina.net/henrylee2cn/blog/505535
贴图结论已验证
二、关于有名返回值和匿名返回值的Demo
func main() {
fmt.Println("a return:", a())
}
func a() (i int){
defer func() {
i++
fmt.Println("a defer2:", i)
}()
defer func() {
i++
fmt.Println("a defer1:", i)
}()
return i
}
func main() {
fmt.Println("b return:", b())
}
func b() int {
var i int
defer func() {
i++
fmt.Println("b defer2", i)
}()
defer func() {
i++
fmt.Println("b defer1", i)
}()
return i
}
func main() {
fmt.Println("c return:", c())
}
func c() (i int) {
defer func() {
i++
fmt.Println("c defer2:", i)
}()
defer func() {
i++
fmt.Println("c defer1:", i)
}()
return 3
}
三、一些小demo
1、n次deferproc, >= n+1次deferreturn
func main() {
log.Println("main start \n")
defer fmt.Println("defer ... ")
log.Println("main end \n")
}
执行结果:
2021/02/08 11:44:37 main start
2021/02/08 11:44:37 main end
defer ...
反汇编
TEXT main.main(SB) .../main.go
main.go:8 0x4cbbf0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:8 0x4cbbf9 488b8900000000 MOVQ 0(CX), CX
main.go:8 0x4cbc00 488d842468ffffff LEAQ 0xffffff68(SP), AX
main.go:8 0x4cbc08 483b4110 CMPQ 0x10(CX), AX
main.go:8 0x4cbc0c 0f86e9010000 JBE 0x4cbdfb
main.go:8 0x4cbc12 4881ec18010000 SUBQ $0x118, SP
main.go:8 0x4cbc19 4889ac2410010000 MOVQ BP, 0x110(SP)
main.go:8 0x4cbc21 488dac2410010000 LEAQ 0x110(SP), BP
main.go:9 0x4cbc29 0f57c0 XORPS X0, X0
main.go:9 0x4cbc2c 0f118424b8000000 MOVUPS X0, 0xb8(SP)
main.go:9 0x4cbc34 488d8424b8000000 LEAQ 0xb8(SP), AX
main.go:9 0x4cbc3c 48898424a0000000 MOVQ AX, 0xa0(SP)
main.go:9 0x4cbc44 8400 TESTB AL, 0(AX)
main.go:9 0x4cbc46 488d0df33c0100 LEAQ type.*+80192(SB), CX
main.go:9 0x4cbc4d 48898c24b8000000 MOVQ CX, 0xb8(SP)
main.go:9 0x4cbc55 488d0da4d20400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+320(SB), CX
main.go:9 0x4cbc5c 48898c24c0000000 MOVQ CX, 0xc0(SP)
main.go:9 0x4cbc64 8400 TESTB AL, 0(AX)
main.go:9 0x4cbc66 eb00 JMP 0x4cbc68
main.go:9 0x4cbc68 48898424f8000000 MOVQ AX, 0xf8(SP)
main.go:9 0x4cbc70 48c784240001000001000000 MOVQ $0x1, 0x100(SP)
main.go:9 0x4cbc7c 48c784240801000001000000 MOVQ $0x1, 0x108(SP)
main.go:9 0x4cbc88 48890424 MOVQ AX, 0(SP)
main.go:9 0x4cbc8c 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:9 0x4cbc95 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:9 0x4cbc9e e81dfeffff CALL log.Println(SB)
main.go:10 0x4cbca3 0f57c0 XORPS X0, X0
main.go:10 0x4cbca6 0f118424a8000000 MOVUPS X0, 0xa8(SP)
main.go:10 0x4cbcae 488d8424a8000000 LEAQ 0xa8(SP), AX
main.go:10 0x4cbcb6 4889842498000000 MOVQ AX, 0x98(SP)
main.go:10 0x4cbcbe 8400 TESTB AL, 0(AX)
main.go:10 0x4cbcc0 488d0d793c0100 LEAQ type.*+80192(SB), CX
main.go:10 0x4cbcc7 48898c24a8000000 MOVQ CX, 0xa8(SP)
main.go:10 0x4cbccf 488d0d3ad20400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+336(SB), CX
main.go:10 0x4cbcd6 48898c24b0000000 MOVQ CX, 0xb0(SP)
main.go:10 0x4cbcde 8400 TESTB AL, 0(AX)
main.go:10 0x4cbce0 eb00 JMP 0x4cbce2
main.go:10 0x4cbce2 48898424e0000000 MOVQ AX, 0xe0(SP)
main.go:10 0x4cbcea 48c78424e800000001000000 MOVQ $0x1, 0xe8(SP)
main.go:10 0x4cbcf6 48c78424f000000001000000 MOVQ $0x1, 0xf0(SP)
main.go:10 0x4cbd02 c744243030000000 MOVL $0x30, 0x30(SP)
main.go:10 0x4cbd0a 488d057f540400 LEAQ go.func.*+15(SB), AX
main.go:10 0x4cbd11 4889442448 MOVQ AX, 0x48(SP)
main.go:10 0x4cbd16 488b8424e8000000 MOVQ 0xe8(SP), AX
main.go:10 0x4cbd1e 488b8c24e0000000 MOVQ 0xe0(SP), CX
main.go:10 0x4cbd26 488b9424f0000000 MOVQ 0xf0(SP), DX
main.go:10 0x4cbd2e 48894c2460 MOVQ CX, 0x60(SP)
main.go:10 0x4cbd33 4889442468 MOVQ AX, 0x68(SP)
main.go:10 0x4cbd38 4889542470 MOVQ DX, 0x70(SP)
main.go:10 0x4cbd3d 488d442430 LEAQ 0x30(SP), AX
main.go:10 0x4cbd42 48890424 MOVQ AX, 0(SP)
main.go:10 0x4cbd46 e8454cf6ff CALL runtime.deferprocStack(SB)
main.go:10 0x4cbd4b 85c0 TESTL AX, AX
main.go:10 0x4cbd4d 0f8592000000 JNE 0x4cbde5
main.go:10 0x4cbd53 eb00 JMP 0x4cbd55
main.go:11 0x4cbd55 0f57c0 XORPS X0, X0
main.go:11 0x4cbd58 0f118424b8000000 MOVUPS X0, 0xb8(SP)
main.go:11 0x4cbd60 488d8424b8000000 LEAQ 0xb8(SP), AX
main.go:11 0x4cbd68 4889842490000000 MOVQ AX, 0x90(SP)
main.go:11 0x4cbd70 8400 TESTB AL, 0(AX)
main.go:11 0x4cbd72 488d0dc73b0100 LEAQ type.*+80192(SB), CX
main.go:11 0x4cbd79 48898c24b8000000 MOVQ CX, 0xb8(SP)
main.go:11 0x4cbd81 488d0d98d10400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+352(SB), CX
main.go:11 0x4cbd88 48898c24c0000000 MOVQ CX, 0xc0(SP)
main.go:11 0x4cbd90 8400 TESTB AL, 0(AX)
main.go:11 0x4cbd92 eb00 JMP 0x4cbd94
main.go:11 0x4cbd94 48898424c8000000 MOVQ AX, 0xc8(SP)
main.go:11 0x4cbd9c 48c78424d000000001000000 MOVQ $0x1, 0xd0(SP)
main.go:11 0x4cbda8 48c78424d800000001000000 MOVQ $0x1, 0xd8(SP)
main.go:11 0x4cbdb4 48890424 MOVQ AX, 0(SP)
main.go:11 0x4cbdb8 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:11 0x4cbdc1 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:11 0x4cbdca e8f1fcffff CALL log.Println(SB)
main.go:12 0x4cbdcf 90 NOPL
main.go:12 0x4cbdd0 e8cb51f6ff CALL runtime.deferreturn(SB)
main.go:12 0x4cbdd5 488bac2410010000 MOVQ 0x110(SP), BP
main.go:12 0x4cbddd 4881c418010000 ADDQ $0x118, SP
main.go:12 0x4cbde4 c3 RET
main.go:10 0x4cbde5 90 NOPL
main.go:10 0x4cbde6 e8b551f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cbdeb 488bac2410010000 MOVQ 0x110(SP), BP
main.go:10 0x4cbdf3 4881c418010000 ADDQ $0x118, SP
main.go:10 0x4cbdfa c3 RET
main.go:8 0x4cbdfb e890ddf8ff CALL runtime.morestack_noctxt(SB)
main.go:8 0x4cbe00 e9ebfdffff JMP main.main(SB)
摘取CALL
main.go:9 0x4cbc9e e81dfeffff CALL log.Println(SB)
main.go:10 0x4cbd46 e8454cf6ff CALL runtime.deferprocStack(SB)
main.go:11 0x4cbdca e8f1fcffff CALL log.Println(SB)
main.go:12 0x4cbdd0 e8cb51f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cbde6 e8b551f6ff CALL runtime.deferreturn(SB)
main.go:8 0x4cbdfb e890ddf8ff CALL runtime.morestack_noctxt(SB)
2、
func main() {
log.Println("main start \n")
defer func() {
log.Printf("enter %s", "defer")
}()
log.Println("main end \n")
}
执行结果
2021/02/08 11:47:55 main start
2021/02/08 11:47:55 main end
2021/02/08 11:47:55 enter defer
反汇编
TEXT main.main(SB) .../main.go
main.go:5 0x4cd900 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:5 0x4cd909 488b8900000000 MOVQ 0(CX), CX
main.go:5 0x4cd910 488d4424d8 LEAQ -0x28(SP), AX
main.go:5 0x4cd915 483b4110 CMPQ 0x10(CX), AX
main.go:5 0x4cd919 0f863b010000 JBE 0x4cda5a
main.go:5 0x4cd91f 4881eca8000000 SUBQ $0xa8, SP
main.go:5 0x4cd926 4889ac24a0000000 MOVQ BP, 0xa0(SP)
main.go:5 0x4cd92e 488dac24a0000000 LEAQ 0xa0(SP), BP
main.go:6 0x4cd936 0f57c0 XORPS X0, X0
main.go:6 0x4cd939 0f11442460 MOVUPS X0, 0x60(SP)
main.go:6 0x4cd93e 488d442460 LEAQ 0x60(SP), AX
main.go:6 0x4cd943 4889442458 MOVQ AX, 0x58(SP)
main.go:6 0x4cd948 8400 TESTB AL, 0(AX)
main.go:6 0x4cd94a 488d0def3f0100 LEAQ type.*+80192(SB), CX
main.go:6 0x4cd951 48894c2460 MOVQ CX, 0x60(SP)
main.go:6 0x4cd956 488d0d63d60400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+320(SB), CX
main.go:6 0x4cd95d 48894c2468 MOVQ CX, 0x68(SP)
main.go:6 0x4cd962 8400 TESTB AL, 0(AX)
main.go:6 0x4cd964 eb00 JMP 0x4cd966
main.go:6 0x4cd966 4889842488000000 MOVQ AX, 0x88(SP)
main.go:6 0x4cd96e 48c784249000000001000000 MOVQ $0x1, 0x90(SP)
main.go:6 0x4cd97a 48c784249800000001000000 MOVQ $0x1, 0x98(SP)
main.go:6 0x4cd986 48890424 MOVQ AX, 0(SP)
main.go:6 0x4cd98a 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:6 0x4cd993 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:6 0x4cd99c e82ffeffff CALL log.Println(SB)
main.go:7 0x4cd9a1 c744241800000000 MOVL $0x0, 0x18(SP)
main.go:7 0x4cd9a9 488d05b0580400 LEAQ go.func.*+159(SB), AX
main.go:7 0x4cd9b0 4889442430 MOVQ AX, 0x30(SP)
main.go:7 0x4cd9b5 488d442418 LEAQ 0x18(SP), AX
main.go:7 0x4cd9ba 48890424 MOVQ AX, 0(SP)
main.go:7 0x4cd9be e8cd2ff6ff CALL runtime.deferprocStack(SB)
main.go:7 0x4cd9c3 85c0 TESTL AX, AX
main.go:7 0x4cd9c5 757d JNE 0x4cda44
main.go:7 0x4cd9c7 eb00 JMP 0x4cd9c9
main.go:11 0x4cd9c9 0f57c0 XORPS X0, X0
main.go:11 0x4cd9cc 0f11442460 MOVUPS X0, 0x60(SP)
main.go:11 0x4cd9d1 488d442460 LEAQ 0x60(SP), AX
main.go:11 0x4cd9d6 4889442450 MOVQ AX, 0x50(SP)
main.go:11 0x4cd9db 8400 TESTB AL, 0(AX)
main.go:11 0x4cd9dd 488d0d5c3f0100 LEAQ type.*+80192(SB), CX
main.go:11 0x4cd9e4 48894c2460 MOVQ CX, 0x60(SP)
main.go:11 0x4cd9e9 488d0de0d50400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+336(SB), CX
main.go:11 0x4cd9f0 48894c2468 MOVQ CX, 0x68(SP)
main.go:11 0x4cd9f5 8400 TESTB AL, 0(AX)
main.go:11 0x4cd9f7 eb00 JMP 0x4cd9f9
main.go:11 0x4cd9f9 4889442470 MOVQ AX, 0x70(SP)
main.go:11 0x4cd9fe 48c744247801000000 MOVQ $0x1, 0x78(SP)
main.go:11 0x4cda07 48c784248000000001000000 MOVQ $0x1, 0x80(SP)
main.go:11 0x4cda13 48890424 MOVQ AX, 0(SP)
main.go:11 0x4cda17 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:11 0x4cda20 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:11 0x4cda29 e8a2fdffff CALL log.Println(SB)
main.go:12 0x4cda2e 90 NOPL
main.go:12 0x4cda2f e86c35f6ff CALL runtime.deferreturn(SB)
main.go:12 0x4cda34 488bac24a0000000 MOVQ 0xa0(SP), BP
main.go:12 0x4cda3c 4881c4a8000000 ADDQ $0xa8, SP
main.go:12 0x4cda43 c3 RET
main.go:7 0x4cda44 90 NOPL
main.go:7 0x4cda45 e85635f6ff CALL runtime.deferreturn(SB)
main.go:7 0x4cda4a 488bac24a0000000 MOVQ 0xa0(SP), BP
main.go:7 0x4cda52 4881c4a8000000 ADDQ $0xa8, SP
main.go:7 0x4cda59 c3 RET
main.go:5 0x4cda5a e831c1f8ff CALL runtime.morestack_noctxt(SB)
main.go:5 0x4cda5f e99cfeffff JMP main.main(SB)
:-1 0x4cda64 cc INT $0x3
:-1 0x4cda65 cc INT $0x3
:-1 0x4cda66 cc INT $0x3
:-1 0x4cda67 cc INT $0x3
:-1 0x4cda68 cc INT $0x3
:-1 0x4cda69 cc INT $0x3
:-1 0x4cda6a cc INT $0x3
:-1 0x4cda6b cc INT $0x3
:-1 0x4cda6c cc INT $0x3
:-1 0x4cda6d cc INT $0x3
:-1 0x4cda6e cc INT $0x3
:-1 0x4cda6f cc INT $0x3
TEXT main.main.func1(SB) .../main.go
main.go:7 0x4cda70 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:7 0x4cda79 488b8900000000 MOVQ 0(CX), CX
main.go:7 0x4cda80 483b6110 CMPQ 0x10(CX), SP
main.go:7 0x4cda84 0f8694000000 JBE 0x4cdb1e
main.go:7 0x4cda8a 4883ec60 SUBQ $0x60, SP
main.go:7 0x4cda8e 48896c2458 MOVQ BP, 0x58(SP)
main.go:7 0x4cda93 488d6c2458 LEAQ 0x58(SP), BP
main.go:8 0x4cda98 0f57c0 XORPS X0, X0
main.go:8 0x4cda9b 0f11442430 MOVUPS X0, 0x30(SP)
main.go:8 0x4cdaa0 488d442430 LEAQ 0x30(SP), AX
main.go:8 0x4cdaa5 4889442428 MOVQ AX, 0x28(SP)
main.go:8 0x4cdaaa 8400 TESTB AL, 0(AX)
main.go:8 0x4cdaac 488d0d8d3e0100 LEAQ type.*+80192(SB), CX
main.go:8 0x4cdab3 48894c2430 MOVQ CX, 0x30(SP)
main.go:8 0x4cdab8 488d0d21d50400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+352(SB), CX
main.go:8 0x4cdabf 48894c2438 MOVQ CX, 0x38(SP)
main.go:8 0x4cdac4 8400 TESTB AL, 0(AX)
main.go:8 0x4cdac6 eb00 JMP 0x4cdac8
main.go:8 0x4cdac8 4889442440 MOVQ AX, 0x40(SP)
main.go:8 0x4cdacd 48c744244801000000 MOVQ $0x1, 0x48(SP)
main.go:8 0x4cdad6 48c744245001000000 MOVQ $0x1, 0x50(SP)
main.go:8 0x4cdadf 488d05a3cd0300 LEAQ go.string.*+2441(SB), AX
main.go:8 0x4cdae6 48890424 MOVQ AX, 0(SP)
main.go:8 0x4cdaea 48c744240808000000 MOVQ $0x8, 0x8(SP)
main.go:8 0x4cdaf3 488b442440 MOVQ 0x40(SP), AX
main.go:8 0x4cdaf8 4889442410 MOVQ AX, 0x10(SP)
main.go:8 0x4cdafd 48c744241801000000 MOVQ $0x1, 0x18(SP)
main.go:8 0x4cdb06 48c744242001000000 MOVQ $0x1, 0x20(SP)
main.go:8 0x4cdb0f e80cfcffff CALL log.Printf(SB)
main.go:10 0x4cdb14 488b6c2458 MOVQ 0x58(SP), BP
main.go:10 0x4cdb19 4883c460 ADDQ $0x60, SP
main.go:10 0x4cdb1d c3 RET
main.go:7 0x4cdb1e e86dc0f8ff CALL runtime.morestack_noctxt(SB)
main.go:7 0x4cdb23 e948ffffff JMP main.main.func1(SB)
摘取CALL
main.go:6 0x4cd99c e82ffeffff CALL log.Println(SB)
main.go:7 0x4cd9be e8cd2ff6ff CALL runtime.deferprocStack(SB)
main.go:11 0x4cda29 e8a2fdffff CALL log.Println(SB)
main.go:12 0x4cda2f e86c35f6ff CALL runtime.deferreturn(SB)
main.go:7 0x4cda45 e85635f6ff CALL runtime.deferreturn(SB)
main.go:5 0x4cda5a e831c1f8ff CALL runtime.morestack_noctxt(SB)
###############################下面是 func1 的 CALL
main.go:8 0x4cdb0f e80cfcffff CALL log.Printf(SB)
main.go:7 0x4cdb1e e86dc0f8ff CALL runtime.morestack_noctxt(SB)
3、
func main() {
log.Println("main start \n")
defer func (msg string) func() {
start := time.Now()
log.Printf("enter %s", msg)
return func() {
log.Printf("exit %s (%s)", msg, time.Since(start)) //闭包引发逃逸,堆上对象赋值,触发垃圾回收机制
}
}("defer")()
log.Println("main end \n")
}
执行结果
2021/02/08 11:56:45 main start
2021/02/08 11:56:45 enter defer
2021/02/08 11:56:45 main end
2021/02/08 11:56:45 exit defer (0s)
反汇编
TEXT main.main(SB) .../main.go
main.go:8 0x4cecb0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:8 0x4cecb9 488b8900000000 MOVQ 0(CX), CX
main.go:8 0x4cecc0 488d4424d0 LEAQ -0x30(SP), AX
main.go:8 0x4cecc5 483b4110 CMPQ 0x10(CX), AX
main.go:8 0x4cecc9 0f865e010000 JBE 0x4cee2d
main.go:8 0x4ceccf 4881ecb0000000 SUBQ $0xb0, SP
main.go:8 0x4cecd6 4889ac24a8000000 MOVQ BP, 0xa8(SP)
main.go:8 0x4cecde 488dac24a8000000 LEAQ 0xa8(SP), BP
main.go:9 0x4cece6 0f57c0 XORPS X0, X0
main.go:9 0x4cece9 0f11442468 MOVUPS X0, 0x68(SP)
main.go:9 0x4cecee 488d442468 LEAQ 0x68(SP), AX
main.go:9 0x4cecf3 4889442458 MOVQ AX, 0x58(SP)
main.go:9 0x4cecf8 8400 TESTB AL, 0(AX)
main.go:9 0x4cecfa 488d0d5f4d0100 LEAQ runtime.rodata+80480(SB), CX
main.go:9 0x4ced01 48894c2468 MOVQ CX, 0x68(SP)
main.go:9 0x4ced06 488d0d73e70400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+320(SB), CX
main.go:9 0x4ced0d 48894c2470 MOVQ CX, 0x70(SP)
main.go:9 0x4ced12 8400 TESTB AL, 0(AX)
main.go:9 0x4ced14 eb00 JMP 0x4ced16
main.go:9 0x4ced16 4889842490000000 MOVQ AX, 0x90(SP)
main.go:9 0x4ced1e 48c784249800000001000000 MOVQ $0x1, 0x98(SP)
main.go:9 0x4ced2a 48c78424a000000001000000 MOVQ $0x1, 0xa0(SP)
main.go:9 0x4ced36 48890424 MOVQ AX, 0(SP)
main.go:9 0x4ced3a 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:9 0x4ced43 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:9 0x4ced4c e82ffeffff CALL log.Println(SB)
main.go:16 0x4ced51 488d057bd90300 LEAQ go.string.*+1011(SB), AX
main.go:16 0x4ced58 48890424 MOVQ AX, 0(SP)
main.go:16 0x4ced5c 48c744240805000000 MOVQ $0x5, 0x8(SP)
main.go:16 0x4ced65 e876020000 CALL main.main.func1(SB)
main.go:16 0x4ced6a 488b442410 MOVQ 0x10(SP), AX
main.go:16 0x4ced6f 4889442460 MOVQ AX, 0x60(SP)
main.go:10 0x4ced74 c744241800000000 MOVL $0x0, 0x18(SP)
main.go:10 0x4ced7c 4889442430 MOVQ AX, 0x30(SP)
main.go:10 0x4ced81 488d442418 LEAQ 0x18(SP), AX
main.go:10 0x4ced86 48890424 MOVQ AX, 0(SP)
main.go:10 0x4ced8a e8011cf6ff CALL runtime.deferprocStack(SB)
main.go:10 0x4ced8f 85c0 TESTL AX, AX
main.go:10 0x4ced91 0f8580000000 JNE 0x4cee17
main.go:10 0x4ced97 eb00 JMP 0x4ced99
main.go:17 0x4ced99 0f57c0 XORPS X0, X0
main.go:17 0x4ced9c 0f11442468 MOVUPS X0, 0x68(SP)
main.go:17 0x4ceda1 488d442468 LEAQ 0x68(SP), AX
main.go:17 0x4ceda6 4889442450 MOVQ AX, 0x50(SP)
main.go:17 0x4cedab 8400 TESTB AL, 0(AX)
main.go:17 0x4cedad 488d0dac4c0100 LEAQ runtime.rodata+80480(SB), CX
main.go:17 0x4cedb4 48894c2468 MOVQ CX, 0x68(SP)
main.go:17 0x4cedb9 488d0dd0e60400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+336(SB), CX
main.go:17 0x4cedc0 48894c2470 MOVQ CX, 0x70(SP)
main.go:17 0x4cedc5 8400 TESTB AL, 0(AX)
main.go:17 0x4cedc7 eb00 JMP 0x4cedc9
main.go:17 0x4cedc9 4889442478 MOVQ AX, 0x78(SP)
main.go:17 0x4cedce 48c784248000000001000000 MOVQ $0x1, 0x80(SP)
main.go:17 0x4cedda 48c784248800000001000000 MOVQ $0x1, 0x88(SP)
main.go:17 0x4cede6 48890424 MOVQ AX, 0(SP)
main.go:17 0x4cedea 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:17 0x4cedf3 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:17 0x4cedfc e87ffdffff CALL log.Println(SB)
main.go:18 0x4cee01 90 NOPL
main.go:18 0x4cee02 e89921f6ff CALL runtime.deferreturn(SB)
main.go:18 0x4cee07 488bac24a8000000 MOVQ 0xa8(SP), BP
main.go:18 0x4cee0f 4881c4b0000000 ADDQ $0xb0, SP
main.go:18 0x4cee16 c3 RET
main.go:10 0x4cee17 90 NOPL
main.go:10 0x4cee18 e88321f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cee1d 488bac24a8000000 MOVQ 0xa8(SP), BP
main.go:10 0x4cee25 4881c4b0000000 ADDQ $0xb0, SP
main.go:10 0x4cee2c c3 RET
main.go:8 0x4cee2d e85eadf8ff CALL runtime.morestack_noctxt(SB)
main.go:8 0x4cee32 e979feffff JMP main.main(SB)
:-1 0x4cee37 cc INT $0x3
:-1 0x4cee38 cc INT $0x3
:-1 0x4cee39 cc INT $0x3
:-1 0x4cee3a cc INT $0x3
:-1 0x4cee3b cc INT $0x3
:-1 0x4cee3c cc INT $0x3
:-1 0x4cee3d cc INT $0x3
:-1 0x4cee3e cc INT $0x3
:-1 0x4cee3f cc INT $0x3
TEXT main.main.func1.1(SB) .../main.go
main.go:13 0x4cee40 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:13 0x4cee49 488b8900000000 MOVQ 0(CX), CX
main.go:13 0x4cee50 488d4424c8 LEAQ -0x38(SP), AX
main.go:13 0x4cee55 483b4110 CMPQ 0x10(CX), AX
main.go:13 0x4cee59 0f866e010000 JBE 0x4cefcd
main.go:13 0x4cee5f 4881ecb8000000 SUBQ $0xb8, SP
main.go:13 0x4cee66 4889ac24b0000000 MOVQ BP, 0xb0(SP)
main.go:13 0x4cee6e 488dac24b0000000 LEAQ 0xb0(SP), BP
main.go:13 0x4cee76 488b4208 MOVQ 0x8(DX), AX
main.go:13 0x4cee7a 488b4a10 MOVQ 0x10(DX), CX
main.go:13 0x4cee7e 4889442450 MOVQ AX, 0x50(SP)
main.go:13 0x4cee83 48894c2458 MOVQ CX, 0x58(SP)
main.go:13 0x4cee88 488d4218 LEAQ 0x18(DX), AX
main.go:13 0x4cee8c 4889442448 MOVQ AX, 0x48(SP)
main.go:14 0x4cee91 488b4220 MOVQ 0x20(DX), AX
main.go:14 0x4cee95 488b4a18 MOVQ 0x18(DX), CX
main.go:14 0x4cee99 488b5228 MOVQ 0x28(DX), DX
main.go:14 0x4cee9d 48894c2478 MOVQ CX, 0x78(SP)
main.go:14 0x4ceea2 4889842480000000 MOVQ AX, 0x80(SP)
main.go:14 0x4ceeaa 4889942488000000 MOVQ DX, 0x88(SP)
main.go:14 0x4ceeb2 48890c24 MOVQ CX, 0(SP)
main.go:14 0x4ceeb6 4889442408 MOVQ AX, 0x8(SP)
main.go:14 0x4ceebb 4889542410 MOVQ DX, 0x10(SP)
main.go:14 0x4ceec0 e8cb56feff CALL time.Since(SB)
main.go:14 0x4ceec5 488b442418 MOVQ 0x18(SP), AX
main.go:14 0x4ceeca 4889442428 MOVQ AX, 0x28(SP)
main.go:14 0x4ceecf 488b442458 MOVQ 0x58(SP), AX
main.go:14 0x4ceed4 488b4c2450 MOVQ 0x50(SP), CX
main.go:14 0x4ceed9 48890c24 MOVQ CX, 0(SP)
main.go:14 0x4ceedd 4889442408 MOVQ AX, 0x8(SP)
main.go:14 0x4ceee2 e829b1f3ff CALL runtime.convTstring(SB)
main.go:14 0x4ceee7 488b442410 MOVQ 0x10(SP), AX
main.go:14 0x4ceeec 4889442440 MOVQ AX, 0x40(SP)
main.go:14 0x4ceef1 488b442428 MOVQ 0x28(SP), AX
main.go:14 0x4ceef6 48890424 MOVQ AX, 0(SP)
main.go:14 0x4ceefa e891b0f3ff CALL runtime.convT64(SB)
main.go:14 0x4ceeff 488b442408 MOVQ 0x8(SP), AX
main.go:14 0x4cef04 4889442438 MOVQ AX, 0x38(SP)
main.go:14 0x4cef09 0f57c0 XORPS X0, X0
main.go:14 0x4cef0c 0f11842490000000 MOVUPS X0, 0x90(SP)
main.go:14 0x4cef14 0f57c0 XORPS X0, X0
main.go:14 0x4cef17 0f118424a0000000 MOVUPS X0, 0xa0(SP)
main.go:14 0x4cef1f 488d842490000000 LEAQ 0x90(SP), AX
main.go:14 0x4cef27 4889442430 MOVQ AX, 0x30(SP)
main.go:14 0x4cef2c 8400 TESTB AL, 0(AX)
main.go:14 0x4cef2e 488b4c2440 MOVQ 0x40(SP), CX
main.go:14 0x4cef33 488d15264b0100 LEAQ runtime.rodata+80480(SB), DX
main.go:14 0x4cef3a 4889942490000000 MOVQ DX, 0x90(SP)
main.go:14 0x4cef42 48898c2498000000 MOVQ CX, 0x98(SP)
main.go:14 0x4cef4a 8400 TESTB AL, 0(AX)
main.go:14 0x4cef4c 488b442438 MOVQ 0x38(SP), AX
main.go:14 0x4cef51 488d0da8c50200 LEAQ runtime.rodata+177408(SB), CX
main.go:14 0x4cef58 48898c24a0000000 MOVQ CX, 0xa0(SP)
main.go:14 0x4cef60 48898424a8000000 MOVQ AX, 0xa8(SP)
main.go:14 0x4cef68 488b442430 MOVQ 0x30(SP), AX
main.go:14 0x4cef6d 8400 TESTB AL, 0(AX)
main.go:14 0x4cef6f eb00 JMP 0x4cef71
main.go:14 0x4cef71 4889442460 MOVQ AX, 0x60(SP)
main.go:14 0x4cef76 48c744246802000000 MOVQ $0x2, 0x68(SP)
main.go:14 0x4cef7f 48c744247002000000 MOVQ $0x2, 0x70(SP)
main.go:14 0x4cef88 488d057ae80300 LEAQ go.string.*+5417(SB), AX
main.go:14 0x4cef8f 48890424 MOVQ AX, 0(SP)
main.go:14 0x4cef93 48c74424080c000000 MOVQ $0xc, 0x8(SP)
main.go:14 0x4cef9c 488b442460 MOVQ 0x60(SP), AX
main.go:14 0x4cefa1 4889442410 MOVQ AX, 0x10(SP)
main.go:14 0x4cefa6 48c744241802000000 MOVQ $0x2, 0x18(SP)
main.go:14 0x4cefaf 48c744242002000000 MOVQ $0x2, 0x20(SP)
main.go:14 0x4cefb8 e813fbffff CALL log.Printf(SB)
main.go:15 0x4cefbd 488bac24b0000000 MOVQ 0xb0(SP), BP
main.go:15 0x4cefc5 4881c4b8000000 ADDQ $0xb8, SP
main.go:15 0x4cefcc c3 RET
main.go:13 0x4cefcd e81eabf8ff CALL runtime.morestack(SB)
main.go:13 0x4cefd2 e969feffff JMP main.main.func1.1(SB)
:-1 0x4cefd7 cc INT $0x3
:-1 0x4cefd8 cc INT $0x3
:-1 0x4cefd9 cc INT $0x3
:-1 0x4cefda cc INT $0x3
:-1 0x4cefdb cc INT $0x3
:-1 0x4cefdc cc INT $0x3
:-1 0x4cefdd cc INT $0x3
:-1 0x4cefde cc INT $0x3
:-1 0x4cefdf cc INT $0x3
TEXT main.main.func1(SB) .../main.go
main.go:10 0x4cefe0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:10 0x4cefe9 488b8900000000 MOVQ 0(CX), CX
main.go:10 0x4ceff0 488d4424f8 LEAQ -0x8(SP), AX
main.go:10 0x4ceff5 483b4110 CMPQ 0x10(CX), AX
main.go:10 0x4ceff9 0f869c010000 JBE 0x4cf19b
main.go:10 0x4cefff 4881ec88000000 SUBQ $0x88, SP
main.go:10 0x4cf006 4889ac2480000000 MOVQ BP, 0x80(SP)
main.go:10 0x4cf00e 488dac2480000000 LEAQ 0x80(SP), BP
main.go:10 0x4cf016 48c78424a000000000000000 MOVQ $0x0, 0xa0(SP)
main.go:11 0x4cf022 e8e95bfeff CALL time.Now(SB)
main.go:11 0x4cf027 488b0424 MOVQ 0(SP), AX
main.go:11 0x4cf02b 488b4c2408 MOVQ 0x8(SP), CX
main.go:11 0x4cf030 488b542410 MOVQ 0x10(SP), DX
main.go:11 0x4cf035 4889442450 MOVQ AX, 0x50(SP)
main.go:11 0x4cf03a 48894c2458 MOVQ CX, 0x58(SP)
main.go:11 0x4cf03f 4889542460 MOVQ DX, 0x60(SP)
main.go:12 0x4cf044 488b842490000000 MOVQ 0x90(SP), AX
main.go:12 0x4cf04c 488b8c2498000000 MOVQ 0x98(SP), CX
main.go:12 0x4cf054 48890424 MOVQ AX, 0(SP)
main.go:12 0x4cf058 48894c2408 MOVQ CX, 0x8(SP)
main.go:12 0x4cf05d e8aeaff3ff CALL runtime.convTstring(SB)
main.go:12 0x4cf062 488b442410 MOVQ 0x10(SP), AX
main.go:12 0x4cf067 4889442438 MOVQ AX, 0x38(SP)
main.go:12 0x4cf06c 0f57c0 XORPS X0, X0
main.go:12 0x4cf06f 0f11442440 MOVUPS X0, 0x40(SP)
main.go:12 0x4cf074 488d442440 LEAQ 0x40(SP), AX
main.go:12 0x4cf079 4889442430 MOVQ AX, 0x30(SP)
main.go:12 0x4cf07e 8400 TESTB AL, 0(AX)
main.go:12 0x4cf080 488b4c2438 MOVQ 0x38(SP), CX
main.go:12 0x4cf085 488d15d4490100 LEAQ runtime.rodata+80480(SB), DX
main.go:12 0x4cf08c 4889542440 MOVQ DX, 0x40(SP)
main.go:12 0x4cf091 48894c2448 MOVQ CX, 0x48(SP)
main.go:12 0x4cf096 8400 TESTB AL, 0(AX)
main.go:12 0x4cf098 eb00 JMP 0x4cf09a
main.go:12 0x4cf09a 4889442468 MOVQ AX, 0x68(SP)
main.go:12 0x4cf09f 48c744247001000000 MOVQ $0x1, 0x70(SP)
main.go:12 0x4cf0a8 48c744247801000000 MOVQ $0x1, 0x78(SP)
main.go:12 0x4cf0b1 488d05b5db0300 LEAQ go.string.*+2445(SB), AX
main.go:12 0x4cf0b8 48890424 MOVQ AX, 0(SP)
main.go:12 0x4cf0bc 48c744240808000000 MOVQ $0x8, 0x8(SP)
main.go:12 0x4cf0c5 488b442468 MOVQ 0x68(SP), AX
main.go:12 0x4cf0ca 4889442410 MOVQ AX, 0x10(SP)
main.go:12 0x4cf0cf 48c744241801000000 MOVQ $0x1, 0x18(SP)
main.go:12 0x4cf0d8 48c744242001000000 MOVQ $0x1, 0x20(SP)
main.go:12 0x4cf0e1 e8eaf9ffff CALL log.Printf(SB)
main.go:13 0x4cf0e6 488d05f3590200 LEAQ runtime.rodata+150240(SB), AX
main.go:13 0x4cf0ed 48890424 MOVQ AX, 0(SP)
main.go:13 0x4cf0f1 e87adaf3ff CALL runtime.newobject(SB) //闭包引用对象逃逸
main.go:13 0x4cf0f6 488b442408 MOVQ 0x8(SP), AX
main.go:13 0x4cf0fb 4889442428 MOVQ AX, 0x28(SP)
main.go:13 0x4cf100 488d0d39fdffff LEAQ 0xfffffd39(IP), CX
main.go:13 0x4cf107 488908 MOVQ CX, 0(AX)
main.go:13 0x4cf10a 488b442428 MOVQ 0x28(SP), AX
main.go:13 0x4cf10f 8400 TESTB AL, 0(AX)
main.go:13 0x4cf111 488b8c2498000000 MOVQ 0x98(SP), CX
main.go:13 0x4cf119 488b942490000000 MOVQ 0x90(SP), DX
main.go:13 0x4cf121 48894810 MOVQ CX, 0x10(AX)
main.go:13 0x4cf125 488d7808 LEAQ 0x8(AX), DI
main.go:13 0x4cf129 833db08e100000 CMPL $0x0, runtime.writeBarrier(SB) //堆上对象赋值触发写屏蔽,runtime.writeBarrier是一个包含写屏障状态的结构体,其中的 enabled 字段表示写屏障的开启与关闭;
main.go:13 0x4cf130 7402 JE 0x4cf134
main.go:13 0x4cf132 eb5d JMP 0x4cf191
main.go:13 0x4cf134 48895008 MOVQ DX, 0x8(AX)
main.go:13 0x4cf138 eb00 JMP 0x4cf13a
main.go:13 0x4cf13a 488b4c2428 MOVQ 0x28(SP), CX
main.go:13 0x4cf13f 8401 TESTB AL, 0(CX)
main.go:13 0x4cf141 488b542450 MOVQ 0x50(SP), DX
main.go:13 0x4cf146 488b5c2458 MOVQ 0x58(SP), BX
main.go:13 0x4cf14b 488b442460 MOVQ 0x60(SP), AX
main.go:13 0x4cf150 48895118 MOVQ DX, 0x18(CX)
main.go:13 0x4cf154 48895920 MOVQ BX, 0x20(CX)
main.go:13 0x4cf158 488d7928 LEAQ 0x28(CX), DI
main.go:13 0x4cf15c 833d7d8e100000 CMPL $0x0, runtime.writeBarrier(SB)//堆上对象赋值触发写屏蔽,runtime.writeBarrier是一个包含写屏障状态的结构体,其中的 enabled 字段表示写屏障的开启与关闭;
main.go:13 0x4cf163 7402 JE 0x4cf167
main.go:13 0x4cf165 eb23 JMP 0x4cf18a
main.go:13 0x4cf167 48894128 MOVQ AX, 0x28(CX)
main.go:13 0x4cf16b eb00 JMP 0x4cf16d
main.go:13 0x4cf16d 488b442428 MOVQ 0x28(SP), AX
main.go:13 0x4cf172 48898424a0000000 MOVQ AX, 0xa0(SP)
main.go:13 0x4cf17a 488bac2480000000 MOVQ 0x80(SP), BP
main.go:13 0x4cf182 4881c488000000 ADDQ $0x88, SP
main.go:13 0x4cf189 c3 RET
main.go:13 0x4cf18a e8f1c9f8ff CALL runtime.gcWriteBarrier(SB) //执行写请求,处理gc相关逻辑
main.go:13 0x4cf18f ebdc JMP 0x4cf16d
main.go:13 0x4cf191 4889d0 MOVQ DX, AX
main.go:13 0x4cf194 e8e7c9f8ff CALL runtime.gcWriteBarrier(SB) //执行写请求,处理gc相关逻辑
main.go:13 0x4cf199 eb9f JMP 0x4cf13a
main.go:10 0x4cf19b e8f0a9f8ff CALL runtime.morestack_noctxt(SB)
main.go:10 0x4cf1a0 e93bfeffff JMP main.main.func1(SB)
:-1 0x4cf1a5 cc INT $0x3
:-1 0x4cf1a6 cc INT $0x3
:-1 0x4cf1a7 cc INT $0x3
:-1 0x4cf1a8 cc INT $0x3
:-1 0x4cf1a9 cc INT $0x3
:-1 0x4cf1aa cc INT $0x3
:-1 0x4cf1ab cc INT $0x3
:-1 0x4cf1ac cc INT $0x3
:-1 0x4cf1ad cc INT $0x3
:-1 0x4cf1ae cc INT $0x3
:-1 0x4cf1af cc INT $0x3
提取CALL
main.go:9 0x4ced4c e82ffeffff CALL log.Println(SB)
main.go:16 0x4ced65 e876020000 CALL main.main.func1(SB)
main.go:10 0x4ced8a e8011cf6ff CALL runtime.deferprocStack(SB)
main.go:17 0x4cedfc e87ffdffff CALL log.Println(SB)
main.go:18 0x4cee02 e89921f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cee18 e88321f6ff CALL runtime.deferreturn(SB)
main.go:8 0x4cee2d e85eadf8ff CALL runtime.morestack_noctxt(SB)
############################下面是 func1.1 的 CALL
main.go:14 0x4ceec0 e8cb56feff CALL time.Since(SB)
main.go:14 0x4ceee2 e829b1f3ff CALL runtime.convTstring(SB)
main.go:14 0x4ceefa e891b0f3ff CALL runtime.convT64(SB)
main.go:14 0x4cefb8 e813fbffff CALL log.Printf(SB)
main.go:13 0x4cefcd e81eabf8ff CALL runtime.morestack(SB)
###########################下面是 func1 的 CALL
main.go:11 0x4cf022 e8e95bfeff CALL time.Now(SB)
main.go:12 0x4cf05d e8aeaff3ff CALL runtime.convTstring(SB)
main.go:12 0x4cf0e1 e8eaf9ffff CALL log.Printf(SB)
main.go:13 0x4cf0f1 e87adaf3ff CALL runtime.newobject(SB)
main.go:13 0x4cf18a e8f1c9f8ff CALL runtime.gcWriteBarrier(SB)
main.go:13 0x4cf194 e8e7c9f8ff CALL runtime.gcWriteBarrier(SB)
main.go:10 0x4cf19b e8f0a9f8ff CALL runtime.morestack_noctxt(SB)
4、
func main() {
log.Println("main start \n")
defer func (msg string) func() {
start := time.Now()
log.Printf("enter %s", msg)
return func(msg string, start time.Time) func() {
log.Printf("enter %s (%s)", msg, time.Since(start))
return func() {
log.Println("start to exit...")
}
}("second defer", start)
}("first defer")()
log.Println("main end \n")
}
执行结果
2021/02/08 12:05:06 main start
2021/02/08 12:05:06 enter first defer
2021/02/08 12:05:06 enter second defer (0s)
2021/02/08 12:05:06 main end
2021/02/08 12:05:06 start to exit...
反汇编
TEXT main.main(SB) .../main.go
main.go:8 0x4cecb0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:8 0x4cecb9 488b8900000000 MOVQ 0(CX), CX
main.go:8 0x4cecc0 488d4424d0 LEAQ -0x30(SP), AX
main.go:8 0x4cecc5 483b4110 CMPQ 0x10(CX), AX
main.go:8 0x4cecc9 0f865e010000 JBE 0x4cee2d
main.go:8 0x4ceccf 4881ecb0000000 SUBQ $0xb0, SP
main.go:8 0x4cecd6 4889ac24a8000000 MOVQ BP, 0xa8(SP)
main.go:8 0x4cecde 488dac24a8000000 LEAQ 0xa8(SP), BP
main.go:9 0x4cece6 0f57c0 XORPS X0, X0
main.go:9 0x4cece9 0f11442468 MOVUPS X0, 0x68(SP)
main.go:9 0x4cecee 488d442468 LEAQ 0x68(SP), AX
main.go:9 0x4cecf3 4889442458 MOVQ AX, 0x58(SP)
main.go:9 0x4cecf8 8400 TESTB AL, 0(AX)
main.go:9 0x4cecfa 488d0ddf4c0100 LEAQ runtime.types+80352(SB), CX
main.go:9 0x4ced01 48894c2468 MOVQ CX, 0x68(SP)
main.go:9 0x4ced06 488d0d93e60400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+320(SB), CX
main.go:9 0x4ced0d 48894c2470 MOVQ CX, 0x70(SP)
main.go:9 0x4ced12 8400 TESTB AL, 0(AX)
main.go:9 0x4ced14 eb00 JMP 0x4ced16
main.go:9 0x4ced16 4889842490000000 MOVQ AX, 0x90(SP)
main.go:9 0x4ced1e 48c784249800000001000000 MOVQ $0x1, 0x98(SP)
main.go:9 0x4ced2a 48c78424a000000001000000 MOVQ $0x1, 0xa0(SP)
main.go:9 0x4ced36 48890424 MOVQ AX, 0(SP)
main.go:9 0x4ced3a 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:9 0x4ced43 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:9 0x4ced4c e82ffeffff CALL log.Println(SB)
main.go:19 0x4ced51 488d051ce60300 LEAQ go.string.*+4532(SB), AX
main.go:19 0x4ced58 48890424 MOVQ AX, 0(SP)
main.go:19 0x4ced5c 48c74424080b000000 MOVQ $0xb, 0x8(SP)
main.go:19 0x4ced65 e8f6020000 CALL main.main.func1(SB)
main.go:19 0x4ced6a 488b442410 MOVQ 0x10(SP), AX
main.go:19 0x4ced6f 4889442460 MOVQ AX, 0x60(SP)
main.go:10 0x4ced74 c744241800000000 MOVL $0x0, 0x18(SP)
main.go:10 0x4ced7c 4889442430 MOVQ AX, 0x30(SP)
main.go:10 0x4ced81 488d442418 LEAQ 0x18(SP), AX
main.go:10 0x4ced86 48890424 MOVQ AX, 0(SP)
main.go:10 0x4ced8a e8011cf6ff CALL runtime.deferprocStack(SB)
main.go:10 0x4ced8f 85c0 TESTL AX, AX
main.go:10 0x4ced91 0f8580000000 JNE 0x4cee17
main.go:10 0x4ced97 eb00 JMP 0x4ced99
main.go:20 0x4ced99 0f57c0 XORPS X0, X0
main.go:20 0x4ced9c 0f11442468 MOVUPS X0, 0x68(SP)
main.go:20 0x4ceda1 488d442468 LEAQ 0x68(SP), AX
main.go:20 0x4ceda6 4889442450 MOVQ AX, 0x50(SP)
main.go:20 0x4cedab 8400 TESTB AL, 0(AX)
main.go:20 0x4cedad 488d0d2c4c0100 LEAQ runtime.types+80352(SB), CX
main.go:20 0x4cedb4 48894c2468 MOVQ CX, 0x68(SP)
main.go:20 0x4cedb9 488d0df0e50400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+336(SB), CX
main.go:20 0x4cedc0 48894c2470 MOVQ CX, 0x70(SP)
main.go:20 0x4cedc5 8400 TESTB AL, 0(AX)
main.go:20 0x4cedc7 eb00 JMP 0x4cedc9
main.go:20 0x4cedc9 4889442478 MOVQ AX, 0x78(SP)
main.go:20 0x4cedce 48c784248000000001000000 MOVQ $0x1, 0x80(SP)
main.go:20 0x4cedda 48c784248800000001000000 MOVQ $0x1, 0x88(SP)
main.go:20 0x4cede6 48890424 MOVQ AX, 0(SP)
main.go:20 0x4cedea 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:20 0x4cedf3 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:20 0x4cedfc e87ffdffff CALL log.Println(SB)
main.go:21 0x4cee01 90 NOPL
main.go:21 0x4cee02 e89921f6ff CALL runtime.deferreturn(SB)
main.go:21 0x4cee07 488bac24a8000000 MOVQ 0xa8(SP), BP
main.go:21 0x4cee0f 4881c4b0000000 ADDQ $0xb0, SP
main.go:21 0x4cee16 c3 RET
main.go:10 0x4cee17 90 NOPL
main.go:10 0x4cee18 e88321f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cee1d 488bac24a8000000 MOVQ 0xa8(SP), BP
main.go:10 0x4cee25 4881c4b0000000 ADDQ $0xb0, SP
main.go:10 0x4cee2c c3 RET
main.go:8 0x4cee2d e85eadf8ff CALL runtime.morestack_noctxt(SB)
main.go:8 0x4cee32 e979feffff JMP main.main(SB)
:-1 0x4cee37 cc INT $0x3
:-1 0x4cee38 cc INT $0x3
:-1 0x4cee39 cc INT $0x3
:-1 0x4cee3a cc INT $0x3
:-1 0x4cee3b cc INT $0x3
:-1 0x4cee3c cc INT $0x3
:-1 0x4cee3d cc INT $0x3
:-1 0x4cee3e cc INT $0x3
:-1 0x4cee3f cc INT $0x3
TEXT main.main.func1.1.1(SB) .../main.go
main.go:15 0x4cee40 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:15 0x4cee49 488b8900000000 MOVQ 0(CX), CX
main.go:15 0x4cee50 483b6110 CMPQ 0x10(CX), SP
main.go:15 0x4cee54 767a JBE 0x4ceed0
main.go:15 0x4cee56 4883ec50 SUBQ $0x50, SP
main.go:15 0x4cee5a 48896c2448 MOVQ BP, 0x48(SP)
main.go:15 0x4cee5f 488d6c2448 LEAQ 0x48(SP), BP
main.go:16 0x4cee64 0f57c0 XORPS X0, X0
main.go:16 0x4cee67 0f11442420 MOVUPS X0, 0x20(SP)
main.go:16 0x4cee6c 488d442420 LEAQ 0x20(SP), AX
main.go:16 0x4cee71 4889442418 MOVQ AX, 0x18(SP)
main.go:16 0x4cee76 8400 TESTB AL, 0(AX)
main.go:16 0x4cee78 488d0d614b0100 LEAQ runtime.types+80352(SB), CX
main.go:16 0x4cee7f 48894c2420 MOVQ CX, 0x20(SP)
main.go:16 0x4cee84 488d0d35e50400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+352(SB), CX
main.go:16 0x4cee8b 48894c2428 MOVQ CX, 0x28(SP)
main.go:16 0x4cee90 8400 TESTB AL, 0(AX)
main.go:16 0x4cee92 eb00 JMP 0x4cee94
main.go:16 0x4cee94 4889442430 MOVQ AX, 0x30(SP)
main.go:16 0x4cee99 48c744243801000000 MOVQ $0x1, 0x38(SP)
main.go:16 0x4ceea2 48c744244001000000 MOVQ $0x1, 0x40(SP)
main.go:16 0x4ceeab 48890424 MOVQ AX, 0(SP)
main.go:16 0x4ceeaf 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:16 0x4ceeb8 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:16 0x4ceec1 e8bafcffff CALL log.Println(SB)
main.go:17 0x4ceec6 488b6c2448 MOVQ 0x48(SP), BP
main.go:17 0x4ceecb 4883c450 ADDQ $0x50, SP
main.go:17 0x4ceecf c3 RET
main.go:15 0x4ceed0 e8bbacf8ff CALL runtime.morestack_noctxt(SB)
main.go:15 0x4ceed5 e966ffffff JMP main.main.func1.1.1(SB)
:-1 0x4ceeda cc INT $0x3
:-1 0x4ceedb cc INT $0x3
:-1 0x4ceedc cc INT $0x3
:-1 0x4ceedd cc INT $0x3
:-1 0x4ceede cc INT $0x3
:-1 0x4ceedf cc INT $0x3
TEXT main.main.func1.1(SB) .../main.go
main.go:13 0x4ceee0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:13 0x4ceee9 488b8900000000 MOVQ 0(CX), CX
main.go:13 0x4ceef0 488d4424f8 LEAQ -0x8(SP), AX
main.go:13 0x4ceef5 483b4110 CMPQ 0x10(CX), AX
main.go:13 0x4ceef9 0f8656010000 JBE 0x4cf055
main.go:13 0x4ceeff 4881ec88000000 SUBQ $0x88, SP
main.go:13 0x4cef06 4889ac2480000000 MOVQ BP, 0x80(SP)
main.go:13 0x4cef0e 488dac2480000000 LEAQ 0x80(SP), BP
main.go:13 0x4cef16 48c78424b800000000000000 MOVQ $0x0, 0xb8(SP)
main.go:14 0x4cef22 488b8424a8000000 MOVQ 0xa8(SP), AX
main.go:14 0x4cef2a 488b8c24a0000000 MOVQ 0xa0(SP), CX
main.go:14 0x4cef32 488b9424b0000000 MOVQ 0xb0(SP), DX
main.go:14 0x4cef3a 48890c24 MOVQ CX, 0(SP)
main.go:14 0x4cef3e 4889442408 MOVQ AX, 0x8(SP)
main.go:14 0x4cef43 4889542410 MOVQ DX, 0x10(SP)
main.go:14 0x4cef48 e84356feff CALL time.Since(SB)
main.go:14 0x4cef4d 488b442418 MOVQ 0x18(SP), AX
main.go:14 0x4cef52 4889442428 MOVQ AX, 0x28(SP)
main.go:14 0x4cef57 488b842490000000 MOVQ 0x90(SP), AX
main.go:14 0x4cef5f 488b8c2498000000 MOVQ 0x98(SP), CX
main.go:14 0x4cef67 48890424 MOVQ AX, 0(SP)
main.go:14 0x4cef6b 48894c2408 MOVQ CX, 0x8(SP)
main.go:14 0x4cef70 e89bb0f3ff CALL runtime.convTstring(SB)
main.go:14 0x4cef75 488b442410 MOVQ 0x10(SP), AX
main.go:14 0x4cef7a 4889442440 MOVQ AX, 0x40(SP)
main.go:14 0x4cef7f 488b442428 MOVQ 0x28(SP), AX
main.go:14 0x4cef84 48890424 MOVQ AX, 0(SP)
main.go:14 0x4cef88 e803b0f3ff CALL runtime.convT64(SB)
main.go:14 0x4cef8d 488b442408 MOVQ 0x8(SP), AX
main.go:14 0x4cef92 4889442438 MOVQ AX, 0x38(SP)
main.go:14 0x4cef97 0f57c0 XORPS X0, X0
main.go:14 0x4cef9a 0f11442460 MOVUPS X0, 0x60(SP)
main.go:14 0x4cef9f 0f57c0 XORPS X0, X0
main.go:14 0x4cefa2 0f11442470 MOVUPS X0, 0x70(SP)
main.go:14 0x4cefa7 488d442460 LEAQ 0x60(SP), AX
main.go:14 0x4cefac 4889442430 MOVQ AX, 0x30(SP)
main.go:14 0x4cefb1 8400 TESTB AL, 0(AX)
main.go:14 0x4cefb3 488b4c2440 MOVQ 0x40(SP), CX
main.go:14 0x4cefb8 488d15214a0100 LEAQ runtime.types+80352(SB), DX
main.go:14 0x4cefbf 4889542460 MOVQ DX, 0x60(SP)
main.go:14 0x4cefc4 48894c2468 MOVQ CX, 0x68(SP)
main.go:14 0x4cefc9 8400 TESTB AL, 0(AX)
main.go:14 0x4cefcb 488b442438 MOVQ 0x38(SP), AX
main.go:14 0x4cefd0 488d0d09c40200 LEAQ runtime.types+177120(SB), CX
main.go:14 0x4cefd7 48894c2470 MOVQ CX, 0x70(SP)
main.go:14 0x4cefdc 4889442478 MOVQ AX, 0x78(SP)
main.go:14 0x4cefe1 488b442430 MOVQ 0x30(SP), AX
main.go:14 0x4cefe6 8400 TESTB AL, 0(AX)
main.go:14 0x4cefe8 eb00 JMP 0x4cefea
main.go:14 0x4cefea 4889442448 MOVQ AX, 0x48(SP)
main.go:14 0x4cefef 48c744245002000000 MOVQ $0x2, 0x50(SP)
main.go:14 0x4ceff8 48c744245802000000 MOVQ $0x2, 0x58(SP)
main.go:14 0x4cf001 488d05c5e90300 LEAQ go.string.*+6157(SB), AX
main.go:14 0x4cf008 48890424 MOVQ AX, 0(SP)
main.go:14 0x4cf00c 48c74424080d000000 MOVQ $0xd, 0x8(SP)
main.go:14 0x4cf015 488b442448 MOVQ 0x48(SP), AX
main.go:14 0x4cf01a 4889442410 MOVQ AX, 0x10(SP)
main.go:14 0x4cf01f 48c744241802000000 MOVQ $0x2, 0x18(SP)
main.go:14 0x4cf028 48c744242002000000 MOVQ $0x2, 0x20(SP)
main.go:14 0x4cf031 e89afaffff CALL log.Printf(SB)
main.go:15 0x4cf036 488d0513650400 LEAQ go.func.*+156(SB), AX
main.go:15 0x4cf03d 48898424b8000000 MOVQ AX, 0xb8(SP)
main.go:15 0x4cf045 488bac2480000000 MOVQ 0x80(SP), BP
main.go:15 0x4cf04d 4881c488000000 ADDQ $0x88, SP
main.go:15 0x4cf054 c3 RET
main.go:13 0x4cf055 e836abf8ff CALL runtime.morestack_noctxt(SB)
main.go:13 0x4cf05a e981feffff JMP main.main.func1.1(SB)
:-1 0x4cf05f cc INT $0x3
TEXT main.main.func1(SB) .../main.go
main.go:10 0x4cf060 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:10 0x4cf069 488b8900000000 MOVQ 0(CX), CX
main.go:10 0x4cf070 488d4424f0 LEAQ -0x10(SP), AX
main.go:10 0x4cf075 483b4110 CMPQ 0x10(CX), AX
main.go:10 0x4cf079 0f8643010000 JBE 0x4cf1c2
main.go:10 0x4cf07f 4881ec90000000 SUBQ $0x90, SP
main.go:10 0x4cf086 4889ac2488000000 MOVQ BP, 0x88(SP)
main.go:10 0x4cf08e 488dac2488000000 LEAQ 0x88(SP), BP
main.go:10 0x4cf096 48c78424a800000000000000 MOVQ $0x0, 0xa8(SP)
main.go:11 0x4cf0a2 e8695bfeff CALL time.Now(SB)
main.go:11 0x4cf0a7 488b442408 MOVQ 0x8(SP), AX
main.go:11 0x4cf0ac 488b0c24 MOVQ 0(SP), CX
main.go:11 0x4cf0b0 488b542410 MOVQ 0x10(SP), DX
main.go:11 0x4cf0b5 48894c2458 MOVQ CX, 0x58(SP)
main.go:11 0x4cf0ba 4889442460 MOVQ AX, 0x60(SP)
main.go:11 0x4cf0bf 4889542468 MOVQ DX, 0x68(SP)
main.go:12 0x4cf0c4 488b842498000000 MOVQ 0x98(SP), AX
main.go:12 0x4cf0cc 488b8c24a0000000 MOVQ 0xa0(SP), CX
main.go:12 0x4cf0d4 48890424 MOVQ AX, 0(SP)
main.go:12 0x4cf0d8 48894c2408 MOVQ CX, 0x8(SP)
main.go:12 0x4cf0dd e82eaff3ff CALL runtime.convTstring(SB)
main.go:12 0x4cf0e2 488b442410 MOVQ 0x10(SP), AX
main.go:12 0x4cf0e7 4889442438 MOVQ AX, 0x38(SP)
main.go:12 0x4cf0ec 0f57c0 XORPS X0, X0
main.go:12 0x4cf0ef 0f11442448 MOVUPS X0, 0x48(SP)
main.go:12 0x4cf0f4 488d442448 LEAQ 0x48(SP), AX
main.go:12 0x4cf0f9 4889442430 MOVQ AX, 0x30(SP)
main.go:12 0x4cf0fe 8400 TESTB AL, 0(AX)
main.go:12 0x4cf100 488b4c2438 MOVQ 0x38(SP), CX
main.go:12 0x4cf105 488d15d4480100 LEAQ runtime.types+80352(SB), DX
main.go:12 0x4cf10c 4889542448 MOVQ DX, 0x48(SP)
main.go:12 0x4cf111 48894c2450 MOVQ CX, 0x50(SP)
main.go:12 0x4cf116 8400 TESTB AL, 0(AX)
main.go:12 0x4cf118 eb00 JMP 0x4cf11a
main.go:12 0x4cf11a 4889442470 MOVQ AX, 0x70(SP)
main.go:12 0x4cf11f 48c744247801000000 MOVQ $0x1, 0x78(SP)
main.go:12 0x4cf128 48c784248000000001000000 MOVQ $0x1, 0x80(SP)
main.go:12 0x4cf134 488d050dda0300 LEAQ go.string.*+2440(SB), AX
main.go:12 0x4cf13b 48890424 MOVQ AX, 0(SP)
main.go:12 0x4cf13f 48c744240808000000 MOVQ $0x8, 0x8(SP)
main.go:12 0x4cf148 488b442470 MOVQ 0x70(SP), AX
main.go:12 0x4cf14d 4889442410 MOVQ AX, 0x10(SP)
main.go:12 0x4cf152 48c744241801000000 MOVQ $0x1, 0x18(SP)
main.go:12 0x4cf15b 48c744242001000000 MOVQ $0x1, 0x20(SP)
main.go:12 0x4cf164 e867f9ffff CALL log.Printf(SB)
main.go:18 0x4cf169 488d0533e60300 LEAQ go.string.*+5603(SB), AX
main.go:18 0x4cf170 48890424 MOVQ AX, 0(SP)
main.go:18 0x4cf174 48c74424080c000000 MOVQ $0xc, 0x8(SP)
main.go:18 0x4cf17d 488b442458 MOVQ 0x58(SP), AX
main.go:18 0x4cf182 488b4c2460 MOVQ 0x60(SP), CX
main.go:18 0x4cf187 488b542468 MOVQ 0x68(SP), DX
main.go:18 0x4cf18c 4889442410 MOVQ AX, 0x10(SP)
main.go:18 0x4cf191 48894c2418 MOVQ CX, 0x18(SP)
main.go:18 0x4cf196 4889542420 MOVQ DX, 0x20(SP)
main.go:18 0x4cf19b e840fdffff CALL main.main.func1.1(SB)
main.go:18 0x4cf1a0 488b442428 MOVQ 0x28(SP), AX
main.go:18 0x4cf1a5 4889442440 MOVQ AX, 0x40(SP)
main.go:13 0x4cf1aa 48898424a8000000 MOVQ AX, 0xa8(SP)
main.go:13 0x4cf1b2 488bac2488000000 MOVQ 0x88(SP), BP
main.go:13 0x4cf1ba 4881c490000000 ADDQ $0x90, SP
main.go:13 0x4cf1c1 c3 RET
main.go:10 0x4cf1c2 e8c9a9f8ff CALL runtime.morestack_noctxt(SB)
main.go:10 0x4cf1c7 e994feffff JMP main.main.func1(SB)
:-1 0x4cf1cc cc INT $0x3
:-1 0x4cf1cd cc INT $0x3
:-1 0x4cf1ce cc INT $0x3
:-1 0x4cf1cf cc INT $0x3
提取CALL
main.go:9 0x4ced4c e82ffeffff CALL log.Println(SB)
main.go:19 0x4ced65 e8f6020000 CALL main.main.func1(SB)
main.go:10 0x4ced8a e8011cf6ff CALL runtime.deferprocStack(SB)
main.go:20 0x4cedfc e87ffdffff CALL log.Println(SB)
main.go:21 0x4cee02 e89921f6ff CALL runtime.deferreturn(SB)
main.go:10 0x4cee18 e88321f6ff CALL runtime.deferreturn(SB)
main.go:8 0x4cee2d e85eadf8ff CALL runtime.morestack_noctxt(SB)
#####################下面是 func1.1.1 的 CALL
main.go:16 0x4ceec1 e8bafcffff CALL log.Println(SB)
main.go:15 0x4ceed0 e8bbacf8ff CALL runtime.morestack_noctxt(SB)
#####################下面是 func1.1 的 CALL
main.go:14 0x4cef48 e84356feff CALL time.Since(SB)
main.go:14 0x4cef70 e89bb0f3ff CALL runtime.convTstring(SB)
main.go:14 0x4cef88 e803b0f3ff CALL runtime.convT64(SB)
main.go:14 0x4cf031 e89afaffff CALL log.Printf(SB)
main.go:13 0x4cf055 e836abf8ff CALL runtime.morestack_noctxt(SB)
#####################下面是 func1 的 CALL
main.go:11 0x4cf0a2 e8695bfeff CALL time.Now(SB)
main.go:12 0x4cf0dd e82eaff3ff CALL runtime.convTstring(SB)
main.go:12 0x4cf164 e867f9ffff CALL log.Printf(SB)
main.go:18 0x4cf19b e840fdffff CALL main.main.func1.1(SB)
main.go:10 0x4cf1c2 e8c9a9f8ff CALL runtime.morestack_noctxt(SB)
5、
func main() {
log.Println("main start \n")
defer func() {
log.Println("this is first defer")
defer func() {
log.Println("this is the defer of the first defer")
}()
}()
log.Println("second defer start \n")
defer func() {
log.Println("this is second defer")
}()
log.Println("main end \n")
}
执行结果
2021/02/08 12:10:10 main start
2021/02/08 12:10:10 second defer start
2021/02/08 12:10:10 main end
2021/02/08 12:10:10 this is second defer
2021/02/08 12:10:10 this is first defer
2021/02/08 12:10:10 this is the defer of the first defer
反汇编
TEXT main.main(SB) .../main.go
main.go:5 0x4cb9a0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:5 0x4cb9a9 488b8900000000 MOVQ 0(CX), CX
main.go:5 0x4cb9b0 488d442480 LEAQ -0x80(SP), AX
main.go:5 0x4cb9b5 483b4110 CMPQ 0x10(CX), AX
main.go:5 0x4cb9b9 0f861f020000 JBE 0x4cbbde
main.go:5 0x4cb9bf 4881ec00010000 SUBQ $0x100, SP
main.go:5 0x4cb9c6 4889ac24f8000000 MOVQ BP, 0xf8(SP)
main.go:5 0x4cb9ce 488dac24f8000000 LEAQ 0xf8(SP), BP
main.go:6 0x4cb9d6 0f57c0 XORPS X0, X0
main.go:6 0x4cb9d9 0f118424a0000000 MOVUPS X0, 0xa0(SP)
main.go:6 0x4cb9e1 488d8424a0000000 LEAQ 0xa0(SP), AX
main.go:6 0x4cb9e9 4889842498000000 MOVQ AX, 0x98(SP)
main.go:6 0x4cb9f1 8400 TESTB AL, 0(AX)
main.go:6 0x4cb9f3 488d0d463f0100 LEAQ runtime.rodata+80192(SB), CX
main.go:6 0x4cb9fa 48898c24a0000000 MOVQ CX, 0xa0(SP)
main.go:6 0x4cba02 488d0d17d50400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+320(SB), CX
main.go:6 0x4cba09 48898c24a8000000 MOVQ CX, 0xa8(SP)
main.go:6 0x4cba11 8400 TESTB AL, 0(AX)
main.go:6 0x4cba13 eb00 JMP 0x4cba15
main.go:6 0x4cba15 48898424e0000000 MOVQ AX, 0xe0(SP)
main.go:6 0x4cba1d 48c78424e800000001000000 MOVQ $0x1, 0xe8(SP)
main.go:6 0x4cba29 48c78424f000000001000000 MOVQ $0x1, 0xf0(SP)
main.go:6 0x4cba35 48890424 MOVQ AX, 0(SP)
main.go:6 0x4cba39 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:6 0x4cba42 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:6 0x4cba4b e820feffff CALL log.Println(SB)
main.go:7 0x4cba50 c744241800000000 MOVL $0x0, 0x18(SP)
main.go:7 0x4cba58 488d0519580400 LEAQ go.func.*+162(SB), AX
main.go:7 0x4cba5f 4889442430 MOVQ AX, 0x30(SP)
main.go:7 0x4cba64 488d442418 LEAQ 0x18(SP), AX
main.go:7 0x4cba69 48890424 MOVQ AX, 0(SP)
main.go:7 0x4cba6d e81e4ff6ff CALL runtime.deferprocStack(SB)
main.go:7 0x4cba72 85c0 TESTL AX, AX
main.go:7 0x4cba74 0f854e010000 JNE 0x4cbbc8
main.go:7 0x4cba7a eb00 JMP 0x4cba7c
main.go:13 0x4cba7c 0f57c0 XORPS X0, X0
main.go:13 0x4cba7f 0f118424a0000000 MOVUPS X0, 0xa0(SP)
main.go:13 0x4cba87 488d8424a0000000 LEAQ 0xa0(SP), AX
main.go:13 0x4cba8f 4889842490000000 MOVQ AX, 0x90(SP)
main.go:13 0x4cba97 8400 TESTB AL, 0(AX)
main.go:13 0x4cba99 488d0da03e0100 LEAQ runtime.rodata+80192(SB), CX
main.go:13 0x4cbaa0 48898c24a0000000 MOVQ CX, 0xa0(SP)
main.go:13 0x4cbaa8 488d0d81d40400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+336(SB), CX
main.go:13 0x4cbaaf 48898c24a8000000 MOVQ CX, 0xa8(SP)
main.go:13 0x4cbab7 8400 TESTB AL, 0(AX)
main.go:13 0x4cbab9 eb00 JMP 0x4cbabb
main.go:13 0x4cbabb 48898424c8000000 MOVQ AX, 0xc8(SP)
main.go:13 0x4cbac3 48c78424d000000001000000 MOVQ $0x1, 0xd0(SP)
main.go:13 0x4cbacf 48c78424d800000001000000 MOVQ $0x1, 0xd8(SP)
main.go:13 0x4cbadb 48890424 MOVQ AX, 0(SP)
main.go:13 0x4cbadf 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:13 0x4cbae8 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:13 0x4cbaf1 e87afdffff CALL log.Println(SB)
main.go:14 0x4cbaf6 c744245000000000 MOVL $0x0, 0x50(SP)
main.go:14 0x4cbafe 488d057b570400 LEAQ go.func.*+170(SB), AX
main.go:14 0x4cbb05 4889442468 MOVQ AX, 0x68(SP)
main.go:14 0x4cbb0a 488d442450 LEAQ 0x50(SP), AX
main.go:14 0x4cbb0f 48890424 MOVQ AX, 0(SP)
main.go:14 0x4cbb13 e8784ef6ff CALL runtime.deferprocStack(SB)
main.go:14 0x4cbb18 85c0 TESTL AX, AX
main.go:14 0x4cbb1a 0f8592000000 JNE 0x4cbbb2
main.go:14 0x4cbb20 eb00 JMP 0x4cbb22
main.go:17 0x4cbb22 0f57c0 XORPS X0, X0
main.go:17 0x4cbb25 0f118424a0000000 MOVUPS X0, 0xa0(SP)
main.go:17 0x4cbb2d 488d8424a0000000 LEAQ 0xa0(SP), AX
main.go:17 0x4cbb35 4889842488000000 MOVQ AX, 0x88(SP)
main.go:17 0x4cbb3d 8400 TESTB AL, 0(AX)
main.go:17 0x4cbb3f 488d0dfa3d0100 LEAQ runtime.rodata+80192(SB), CX
main.go:17 0x4cbb46 48898c24a0000000 MOVQ CX, 0xa0(SP)
main.go:17 0x4cbb4e 488d0debd30400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+352(SB), CX
main.go:17 0x4cbb55 48898c24a8000000 MOVQ CX, 0xa8(SP)
main.go:17 0x4cbb5d 8400 TESTB AL, 0(AX)
main.go:17 0x4cbb5f eb00 JMP 0x4cbb61
main.go:17 0x4cbb61 48898424b0000000 MOVQ AX, 0xb0(SP)
main.go:17 0x4cbb69 48c78424b800000001000000 MOVQ $0x1, 0xb8(SP)
main.go:17 0x4cbb75 48c78424c000000001000000 MOVQ $0x1, 0xc0(SP)
main.go:17 0x4cbb81 48890424 MOVQ AX, 0(SP)
main.go:17 0x4cbb85 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:17 0x4cbb8e 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:17 0x4cbb97 e8d4fcffff CALL log.Println(SB)
main.go:18 0x4cbb9c 90 NOPL
main.go:18 0x4cbb9d e8fe53f6ff CALL runtime.deferreturn(SB)
main.go:18 0x4cbba2 488bac24f8000000 MOVQ 0xf8(SP), BP
main.go:18 0x4cbbaa 4881c400010000 ADDQ $0x100, SP
main.go:18 0x4cbbb1 c3 RET
main.go:14 0x4cbbb2 90 NOPL
main.go:14 0x4cbbb3 e8e853f6ff CALL runtime.deferreturn(SB)
main.go:14 0x4cbbb8 488bac24f8000000 MOVQ 0xf8(SP), BP
main.go:14 0x4cbbc0 4881c400010000 ADDQ $0x100, SP
main.go:14 0x4cbbc7 c3 RET
main.go:7 0x4cbbc8 90 NOPL
main.go:7 0x4cbbc9 e8d253f6ff CALL runtime.deferreturn(SB)
main.go:7 0x4cbbce 488bac24f8000000 MOVQ 0xf8(SP), BP
main.go:7 0x4cbbd6 4881c400010000 ADDQ $0x100, SP
main.go:7 0x4cbbdd c3 RET
main.go:5 0x4cbbde e8addff8ff CALL runtime.morestack_noctxt(SB)
main.go:5 0x4cbbe3 e9b8fdffff JMP main.main(SB)
:-1 0x4cbbe8 cc INT $0x3
:-1 0x4cbbe9 cc INT $0x3
:-1 0x4cbbea cc INT $0x3
:-1 0x4cbbeb cc INT $0x3
:-1 0x4cbbec cc INT $0x3
:-1 0x4cbbed cc INT $0x3
:-1 0x4cbbee cc INT $0x3
:-1 0x4cbbef cc INT $0x3
TEXT main.main.func1.1(SB) .../main.go
main.go:9 0x4cbbf0 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:9 0x4cbbf9 488b8900000000 MOVQ 0(CX), CX
main.go:9 0x4cbc00 483b6110 CMPQ 0x10(CX), SP
main.go:9 0x4cbc04 767a JBE 0x4cbc80
main.go:9 0x4cbc06 4883ec50 SUBQ $0x50, SP
main.go:9 0x4cbc0a 48896c2448 MOVQ BP, 0x48(SP)
main.go:9 0x4cbc0f 488d6c2448 LEAQ 0x48(SP), BP
main.go:10 0x4cbc14 0f57c0 XORPS X0, X0
main.go:10 0x4cbc17 0f11442420 MOVUPS X0, 0x20(SP)
main.go:10 0x4cbc1c 488d442420 LEAQ 0x20(SP), AX
main.go:10 0x4cbc21 4889442418 MOVQ AX, 0x18(SP)
main.go:10 0x4cbc26 8400 TESTB AL, 0(AX)
main.go:10 0x4cbc28 488d0d113d0100 LEAQ runtime.rodata+80192(SB), CX
main.go:10 0x4cbc2f 48894c2420 MOVQ CX, 0x20(SP)
main.go:10 0x4cbc34 488d0d15d30400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+368(SB), CX
main.go:10 0x4cbc3b 48894c2428 MOVQ CX, 0x28(SP)
main.go:10 0x4cbc40 8400 TESTB AL, 0(AX)
main.go:10 0x4cbc42 eb00 JMP 0x4cbc44
main.go:10 0x4cbc44 4889442430 MOVQ AX, 0x30(SP)
main.go:10 0x4cbc49 48c744243801000000 MOVQ $0x1, 0x38(SP)
main.go:10 0x4cbc52 48c744244001000000 MOVQ $0x1, 0x40(SP)
main.go:10 0x4cbc5b 48890424 MOVQ AX, 0(SP)
main.go:10 0x4cbc5f 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:10 0x4cbc68 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:10 0x4cbc71 e8fafbffff CALL log.Println(SB)
main.go:11 0x4cbc76 488b6c2448 MOVQ 0x48(SP), BP
main.go:11 0x4cbc7b 4883c450 ADDQ $0x50, SP
main.go:11 0x4cbc7f c3 RET
main.go:9 0x4cbc80 e80bdff8ff CALL runtime.morestack_noctxt(SB)
main.go:9 0x4cbc85 e966ffffff JMP main.main.func1.1(SB)
:-1 0x4cbc8a cc INT $0x3
:-1 0x4cbc8b cc INT $0x3
:-1 0x4cbc8c cc INT $0x3
:-1 0x4cbc8d cc INT $0x3
:-1 0x4cbc8e cc INT $0x3
:-1 0x4cbc8f cc INT $0x3
TEXT main.main.func1(SB) .../main.go
main.go:7 0x4cbc90 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:7 0x4cbc99 488b8900000000 MOVQ 0(CX), CX
main.go:7 0x4cbca0 488d4424f8 LEAQ -0x8(SP), AX
main.go:7 0x4cbca5 483b4110 CMPQ 0x10(CX), AX
main.go:7 0x4cbca9 0f86cd000000 JBE 0x4cbd7c
main.go:7 0x4cbcaf 4881ec88000000 SUBQ $0x88, SP
main.go:7 0x4cbcb6 4889ac2480000000 MOVQ BP, 0x80(SP)
main.go:7 0x4cbcbe 488dac2480000000 LEAQ 0x80(SP), BP
main.go:8 0x4cbcc6 0f57c0 XORPS X0, X0
main.go:8 0x4cbcc9 0f11442458 MOVUPS X0, 0x58(SP)
main.go:8 0x4cbcce 488d442458 LEAQ 0x58(SP), AX
main.go:8 0x4cbcd3 4889442450 MOVQ AX, 0x50(SP)
main.go:8 0x4cbcd8 8400 TESTB AL, 0(AX)
main.go:8 0x4cbcda 488d0d5f3c0100 LEAQ runtime.rodata+80192(SB), CX
main.go:8 0x4cbce1 48894c2458 MOVQ CX, 0x58(SP)
main.go:8 0x4cbce6 488d0d73d20400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+384(SB), CX
main.go:8 0x4cbced 48894c2460 MOVQ CX, 0x60(SP)
main.go:8 0x4cbcf2 8400 TESTB AL, 0(AX)
main.go:8 0x4cbcf4 eb00 JMP 0x4cbcf6
main.go:8 0x4cbcf6 4889442468 MOVQ AX, 0x68(SP)
main.go:8 0x4cbcfb 48c744247001000000 MOVQ $0x1, 0x70(SP)
main.go:8 0x4cbd04 48c744247801000000 MOVQ $0x1, 0x78(SP)
main.go:8 0x4cbd0d 48890424 MOVQ AX, 0(SP)
main.go:8 0x4cbd11 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:8 0x4cbd1a 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:8 0x4cbd23 e848fbffff CALL log.Println(SB)
main.go:9 0x4cbd28 c744241800000000 MOVL $0x0, 0x18(SP)
main.go:9 0x4cbd30 488d0539550400 LEAQ go.func.*+154(SB), AX
main.go:9 0x4cbd37 4889442430 MOVQ AX, 0x30(SP)
main.go:9 0x4cbd3c 488d442418 LEAQ 0x18(SP), AX
main.go:9 0x4cbd41 48890424 MOVQ AX, 0(SP)
main.go:9 0x4cbd45 e8464cf6ff CALL runtime.deferprocStack(SB)
main.go:9 0x4cbd4a 85c0 TESTL AX, AX
main.go:9 0x4cbd4c 7518 JNE 0x4cbd66
main.go:9 0x4cbd4e eb00 JMP 0x4cbd50
main.go:12 0x4cbd50 90 NOPL
main.go:12 0x4cbd51 e84a52f6ff CALL runtime.deferreturn(SB)
main.go:12 0x4cbd56 488bac2480000000 MOVQ 0x80(SP), BP
main.go:12 0x4cbd5e 4881c488000000 ADDQ $0x88, SP
main.go:12 0x4cbd65 c3 RET
main.go:9 0x4cbd66 90 NOPL
main.go:9 0x4cbd67 e83452f6ff CALL runtime.deferreturn(SB)
main.go:9 0x4cbd6c 488bac2480000000 MOVQ 0x80(SP), BP
main.go:9 0x4cbd74 4881c488000000 ADDQ $0x88, SP
main.go:9 0x4cbd7b c3 RET
main.go:7 0x4cbd7c e80fdef8ff CALL runtime.morestack_noctxt(SB)
main.go:7 0x4cbd81 e90affffff JMP main.main.func1(SB)
:-1 0x4cbd86 cc INT $0x3
:-1 0x4cbd87 cc INT $0x3
:-1 0x4cbd88 cc INT $0x3
:-1 0x4cbd89 cc INT $0x3
:-1 0x4cbd8a cc INT $0x3
:-1 0x4cbd8b cc INT $0x3
:-1 0x4cbd8c cc INT $0x3
:-1 0x4cbd8d cc INT $0x3
:-1 0x4cbd8e cc INT $0x3
:-1 0x4cbd8f cc INT $0x3
TEXT main.main.func2(SB) .../main.go
main.go:14 0x4cbd90 65488b0c2528000000 MOVQ GS:0x28, CX
main.go:14 0x4cbd99 488b8900000000 MOVQ 0(CX), CX
main.go:14 0x4cbda0 483b6110 CMPQ 0x10(CX), SP
main.go:14 0x4cbda4 767a JBE 0x4cbe20
main.go:14 0x4cbda6 4883ec50 SUBQ $0x50, SP
main.go:14 0x4cbdaa 48896c2448 MOVQ BP, 0x48(SP)
main.go:14 0x4cbdaf 488d6c2448 LEAQ 0x48(SP), BP
main.go:15 0x4cbdb4 0f57c0 XORPS X0, X0
main.go:15 0x4cbdb7 0f11442420 MOVUPS X0, 0x20(SP)
main.go:15 0x4cbdbc 488d442420 LEAQ 0x20(SP), AX
main.go:15 0x4cbdc1 4889442418 MOVQ AX, 0x18(SP)
main.go:15 0x4cbdc6 8400 TESTB AL, 0(AX)
main.go:15 0x4cbdc8 488d0d713b0100 LEAQ runtime.rodata+80192(SB), CX
main.go:15 0x4cbdcf 48894c2420 MOVQ CX, 0x20(SP)
main.go:15 0x4cbdd4 488d0d95d10400 LEAQ sync/atomic.CompareAndSwapUintptr.args_stackmap+400(SB), CX
main.go:15 0x4cbddb 48894c2428 MOVQ CX, 0x28(SP)
main.go:15 0x4cbde0 8400 TESTB AL, 0(AX)
main.go:15 0x4cbde2 eb00 JMP 0x4cbde4
main.go:15 0x4cbde4 4889442430 MOVQ AX, 0x30(SP)
main.go:15 0x4cbde9 48c744243801000000 MOVQ $0x1, 0x38(SP)
main.go:15 0x4cbdf2 48c744244001000000 MOVQ $0x1, 0x40(SP)
main.go:15 0x4cbdfb 48890424 MOVQ AX, 0(SP)
main.go:15 0x4cbdff 48c744240801000000 MOVQ $0x1, 0x8(SP)
main.go:15 0x4cbe08 48c744241001000000 MOVQ $0x1, 0x10(SP)
main.go:15 0x4cbe11 e85afaffff CALL log.Println(SB)
main.go:16 0x4cbe16 488b6c2448 MOVQ 0x48(SP), BP
main.go:16 0x4cbe1b 4883c450 ADDQ $0x50, SP
main.go:16 0x4cbe1f c3 RET
main.go:14 0x4cbe20 e86bddf8ff CALL runtime.morestack_noctxt(SB)
main.go:14 0x4cbe25 e966ffffff JMP main.main.func2(SB)
提取CALL
main.go:6 0x4cba4b e820feffff CALL log.Println(SB)
main.go:7 0x4cba6d e81e4ff6ff CALL runtime.deferprocStack(SB)
main.go:13 0x4cbaf1 e87afdffff CALL log.Println(SB)
main.go:14 0x4cbb13 e8784ef6ff CALL runtime.deferprocStack(SB)
main.go:17 0x4cbb97 e8d4fcffff CALL log.Println(SB)
main.go:18 0x4cbb9d e8fe53f6ff CALL runtime.deferreturn(SB)
main.go:14 0x4cbbb3 e8e853f6ff CALL runtime.deferreturn(SB)
main.go:7 0x4cbbc9 e8d253f6ff CALL runtime.deferreturn(SB)
main.go:5 0x4cbbde e8addff8ff CALL runtime.morestack_noctxt(SB)
#################下面是 func1.1 的 CALL
main.go:10 0x4cbc71 e8fafbffff CALL log.Println(SB)
main.go:9 0x4cbc80 e80bdff8ff CALL runtime.morestack_noctxt(SB)
#################下面是 func1 的 CALL
main.go:8 0x4cbd23 e848fbffff CALL log.Println(SB)
main.go:9 0x4cbd45 e8464cf6ff CALL runtime.deferprocStack(SB)
main.go:12 0x4cbd51 e84a52f6ff CALL runtime.deferreturn(SB)
main.go:9 0x4cbd67 e83452f6ff CALL runtime.deferreturn(SB)
main.go:7 0x4cbd7c e80fdef8ff CALL runtime.morestack_noctxt(SB)
#################下面是 func2 的 CALL
main.go:15 0x4cbe11 e85afaffff CALL log.Println(SB)
main.go:14 0x4cbe20 e86bddf8ff CALL runtime.morestack_noctxt(SB)
三、关键知识点汇总
1、defer
的实现一定是由编译器和运行时共同完成的
2、defer
关键字使用传值的方式传递参数时会进行预计算,导致不符合预期的结果
3、Go 语言中所有的函数调用都是传值的,虽然 defer
是关键字,但是也继承了这个特性
4、内存分配逃逸分析的场景需了解
5、对deferproc和deferreturn的机制做了解
6、return不是原子操作,执行过程是: 保存返回值(若有)-->执行defer(若有)-->执行ret跳转