golang defer 的不同书写方式导致的差异

godaner已被使用 · · 378 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

三种情况:

package main

import "fmt"

func main() {
    a := 0
    tp := 0
    b := &tp
    // condition 3
    defer func() {
        fmt.Println(a)
        fmt.Println(*b)
        fmt.Println("condition 3 end============")
    }()
    // condition 2
    defer fmt.Println("condition 2 end============")
    defer fmt.Println(*b)
    defer fmt.Println(a)
    // condition 1
    defer func(a int, b *int) {
        fmt.Println(a)
        fmt.Println(*b)
        fmt.Println("condition 1 end============")
    }(a, b)
    a = 1
    *b = 2
}


输出:

0
2
condition 1 end============
0
0
condition 2 end============
1
2
condition 3 end============


具体原因可以参考汇编代码:

"".main STEXT size=646 args=0x0 locals=0x88
    0x0000 00000 (boot.go:5)    TEXT    "".main(SB), ABIInternal, $136-0
    0x0000 00000 (boot.go:5)    MOVQ    TLS, CX
    0x0009 00009 (boot.go:5)    MOVQ    (CX)(TLS*2), CX
    0x0010 00016 (boot.go:5)    LEAQ    -8(SP), AX
    0x0015 00021 (boot.go:5)    CMPQ    AX, 16(CX)
    0x0019 00025 (boot.go:5)    JLS 636
    0x001f 00031 (boot.go:5)    SUBQ    $136, SP
    0x0026 00038 (boot.go:5)    MOVQ    BP, 128(SP)
    0x002e 00046 (boot.go:5)    LEAQ    128(SP), BP
    0x0036 00054 (boot.go:5)    FUNCDATA    $0, gclocals·3e27b3aa6b89137cce48b3379a2a6610(SB)
    0x0036 00054 (boot.go:5)    FUNCDATA    $1, gclocals·8d8af7cdb400daeb6b006e733bd0e383(SB)
    0x0036 00054 (boot.go:5)    FUNCDATA    $3, gclocals·e0c93e5d9179a75f8f23b149ced9dbf5(SB)
    0x0036 00054 (boot.go:5)    FUNCDATA    $4, "".main.stkobj(SB)
    0x0036 00054 (boot.go:6)    PCDATA  $2, $0
    0x0036 00054 (boot.go:6)    PCDATA  $0, $0
    0x0036 00054 (boot.go:6)    MOVQ    $0, "".a+64(SP)
    0x003f 00063 (boot.go:7)    PCDATA  $2, $1
    0x003f 00063 (boot.go:7)    LEAQ    type.int(SB), AX
    0x0046 00070 (boot.go:7)    PCDATA  $2, $0
    0x0046 00070 (boot.go:7)    MOVQ    AX, (SP)
    0x004a 00074 (boot.go:7)    CALL    runtime.newobject(SB)
    0x004f 00079 (boot.go:7)    PCDATA  $2, $1
    0x004f 00079 (boot.go:7)    MOVQ    8(SP), AX
    0x0054 00084 (boot.go:7)    PCDATA  $0, $1
    0x0054 00084 (boot.go:7)    MOVQ    AX, "".b+72(SP)
    0x0059 00089 (boot.go:10)   MOVL    $16, (SP)
    0x0060 00096 (boot.go:10)   PCDATA  $2, $2
    0x0060 00096 (boot.go:10)   LEAQ    "".main.func1·f(SB), CX
    0x0067 00103 (boot.go:10)   PCDATA  $2, $1
    0x0067 00103 (boot.go:10)   MOVQ    CX, 8(SP)
    0x006c 00108 (boot.go:10)   PCDATA  $2, $2
    0x006c 00108 (boot.go:10)   LEAQ    "".a+64(SP), CX
    0x0071 00113 (boot.go:10)   PCDATA  $2, $1
    0x0071 00113 (boot.go:10)   MOVQ    CX, 16(SP)
    0x0076 00118 (boot.go:10)   PCDATA  $2, $0
    0x0076 00118 (boot.go:10)   MOVQ    AX, 24(SP)
    0x007b 00123 (boot.go:10)   CALL    runtime.deferproc(SB)
    0x0080 00128 (boot.go:10)   TESTL   AX, AX
    0x0082 00130 (boot.go:10)   JNE 614
    0x0088 00136 (boot.go:16)   PCDATA  $0, $2
    0x0088 00136 (boot.go:16)   XORPS   X0, X0
    0x008b 00139 (boot.go:16)   MOVUPS  X0, ""..autotmp_9+80(SP)
    0x0090 00144 (boot.go:16)   PCDATA  $2, $1
    0x0090 00144 (boot.go:16)   LEAQ    type.string(SB), AX
    0x0097 00151 (boot.go:16)   PCDATA  $2, $0
    0x0097 00151 (boot.go:16)   MOVQ    AX, ""..autotmp_9+80(SP)
    0x009c 00156 (boot.go:16)   PCDATA  $2, $1
    0x009c 00156 (boot.go:16)   LEAQ    "".statictmp_0(SB), AX
    0x00a3 00163 (boot.go:16)   PCDATA  $2, $0
    0x00a3 00163 (boot.go:16)   MOVQ    AX, ""..autotmp_9+88(SP)
    0x00a8 00168 (boot.go:16)   MOVL    $48, (SP)
    0x00af 00175 (boot.go:16)   PCDATA  $2, $1
    0x00af 00175 (boot.go:16)   LEAQ    fmt.Println·f(SB), AX
    0x00b6 00182 (boot.go:16)   PCDATA  $2, $0
    0x00b6 00182 (boot.go:16)   MOVQ    AX, 8(SP)
    0x00bb 00187 (boot.go:16)   PCDATA  $2, $3
    0x00bb 00187 (boot.go:16)   PCDATA  $0, $1
    0x00bb 00187 (boot.go:16)   LEAQ    ""..autotmp_9+80(SP), CX
    0x00c0 00192 (boot.go:16)   PCDATA  $2, $0
    0x00c0 00192 (boot.go:16)   MOVQ    CX, 16(SP)
    0x00c5 00197 (boot.go:16)   MOVQ    $1, 24(SP)
    0x00ce 00206 (boot.go:16)   MOVQ    $1, 32(SP)
    0x00d7 00215 (boot.go:16)   CALL    runtime.deferproc(SB)
    0x00dc 00220 (boot.go:16)   TESTL   AX, AX
    0x00de 00222 (boot.go:16)   JNE 592
    0x00e4 00228 (boot.go:17)   PCDATA  $2, $1
    0x00e4 00228 (boot.go:17)   MOVQ    "".b+72(SP), AX
    0x00e9 00233 (boot.go:17)   PCDATA  $2, $0
    0x00e9 00233 (boot.go:17)   MOVQ    (AX), CX
    0x00ec 00236 (boot.go:17)   MOVQ    CX, (SP)
    0x00f0 00240 (boot.go:17)   CALL    runtime.convT64(SB)
    0x00f5 00245 (boot.go:17)   PCDATA  $2, $1
    0x00f5 00245 (boot.go:17)   MOVQ    8(SP), AX
    0x00fa 00250 (boot.go:17)   PCDATA  $0, $3
    0x00fa 00250 (boot.go:17)   XORPS   X0, X0
    0x00fd 00253 (boot.go:17)   MOVUPS  X0, ""..autotmp_15+112(SP)
    0x0102 00258 (boot.go:17)   PCDATA  $2, $2
    0x0102 00258 (boot.go:17)   LEAQ    type.int(SB), CX
    0x0109 00265 (boot.go:17)   PCDATA  $2, $1
    0x0109 00265 (boot.go:17)   MOVQ    CX, ""..autotmp_15+112(SP)
    0x010e 00270 (boot.go:17)   PCDATA  $2, $0
    0x010e 00270 (boot.go:17)   MOVQ    AX, ""..autotmp_15+120(SP)
    0x0113 00275 (boot.go:17)   MOVL    $48, (SP)
    0x011a 00282 (boot.go:17)   PCDATA  $2, $1
    0x011a 00282 (boot.go:17)   LEAQ    fmt.Println·f(SB), AX
    0x0121 00289 (boot.go:17)   PCDATA  $2, $0
    0x0121 00289 (boot.go:17)   MOVQ    AX, 8(SP)
    0x0126 00294 (boot.go:17)   PCDATA  $2, $4
    0x0126 00294 (boot.go:17)   PCDATA  $0, $1
    0x0126 00294 (boot.go:17)   LEAQ    ""..autotmp_15+112(SP), DX
    0x012b 00299 (boot.go:17)   PCDATA  $2, $0
    0x012b 00299 (boot.go:17)   MOVQ    DX, 16(SP)
    0x0130 00304 (boot.go:17)   MOVQ    $1, 24(SP)
    0x0139 00313 (boot.go:17)   MOVQ    $1, 32(SP)
    0x0142 00322 (boot.go:17)   CALL    runtime.deferproc(SB)
    0x0147 00327 (boot.go:17)   TESTL   AX, AX
    0x0149 00329 (boot.go:17)   JNE 570
    0x014f 00335 (boot.go:18)   MOVQ    "".a+64(SP), AX
    0x0154 00340 (boot.go:18)   MOVQ    AX, (SP)
    0x0158 00344 (boot.go:18)   CALL    runtime.convT64(SB)
    0x015d 00349 (boot.go:18)   PCDATA  $2, $1
    0x015d 00349 (boot.go:18)   MOVQ    8(SP), AX
    0x0162 00354 (boot.go:18)   PCDATA  $0, $4
    0x0162 00354 (boot.go:18)   XORPS   X0, X0
    0x0165 00357 (boot.go:18)   MOVUPS  X0, ""..autotmp_20+96(SP)
    0x016a 00362 (boot.go:18)   PCDATA  $2, $2
    0x016a 00362 (boot.go:18)   LEAQ    type.int(SB), CX
    0x0171 00369 (boot.go:18)   PCDATA  $2, $1
    0x0171 00369 (boot.go:18)   MOVQ    CX, ""..autotmp_20+96(SP)
    0x0176 00374 (boot.go:18)   PCDATA  $2, $0
    0x0176 00374 (boot.go:18)   MOVQ    AX, ""..autotmp_20+104(SP)
    0x017b 00379 (boot.go:18)   MOVL    $48, (SP)
    0x0182 00386 (boot.go:18)   PCDATA  $2, $1
    0x0182 00386 (boot.go:18)   LEAQ    fmt.Println·f(SB), AX
    0x0189 00393 (boot.go:18)   PCDATA  $2, $0
    0x0189 00393 (boot.go:18)   MOVQ    AX, 8(SP)
    0x018e 00398 (boot.go:18)   PCDATA  $2, $1
    0x018e 00398 (boot.go:18)   PCDATA  $0, $1
    0x018e 00398 (boot.go:18)   LEAQ    ""..autotmp_20+96(SP), AX
    0x0193 00403 (boot.go:18)   PCDATA  $2, $0
    0x0193 00403 (boot.go:18)   MOVQ    AX, 16(SP)
    0x0198 00408 (boot.go:18)   MOVQ    $1, 24(SP)
    0x01a1 00417 (boot.go:18)   MOVQ    $1, 32(SP)
    0x01aa 00426 (boot.go:18)   CALL    runtime.deferproc(SB)
    0x01af 00431 (boot.go:18)   TESTL   AX, AX
    0x01b1 00433 (boot.go:18)   JNE 548
    0x01b3 00435 (boot.go:20)   MOVL    $16, (SP)
    0x01ba 00442 (boot.go:20)   PCDATA  $2, $1
    0x01ba 00442 (boot.go:20)   LEAQ    "".main.func2·f(SB), AX
    0x01c1 00449 (boot.go:20)   PCDATA  $2, $0
    0x01c1 00449 (boot.go:20)   MOVQ    AX, 8(SP)
    0x01c6 00454 (boot.go:20)   MOVQ    "".a+64(SP), AX
    0x01cb 00459 (boot.go:20)   MOVQ    AX, 16(SP)
    0x01d0 00464 (boot.go:20)   PCDATA  $2, $1
    0x01d0 00464 (boot.go:20)   MOVQ    "".b+72(SP), AX
    0x01d5 00469 (boot.go:20)   PCDATA  $2, $0
    0x01d5 00469 (boot.go:20)   MOVQ    AX, 24(SP)
    0x01da 00474 (boot.go:20)   CALL    runtime.deferproc(SB)
    0x01df 00479 (boot.go:20)   TESTL   AX, AX
    0x01e1 00481 (boot.go:20)   JNE 526
    0x01e3 00483 (boot.go:25)   MOVQ    $1, "".a+64(SP)
    0x01ec 00492 (boot.go:26)   PCDATA  $2, $1
    0x01ec 00492 (boot.go:26)   PCDATA  $0, $0
    0x01ec 00492 (boot.go:26)   MOVQ    "".b+72(SP), AX
    0x01f1 00497 (boot.go:26)   PCDATA  $2, $0
    0x01f1 00497 (boot.go:26)   MOVQ    $2, (AX)
    0x01f8 00504 (boot.go:27)   XCHGL   AX, AX
    0x01f9 00505 (boot.go:27)   CALL    runtime.deferreturn(SB)
    0x01fe 00510 (boot.go:27)   MOVQ    128(SP), BP
    0x0206 00518 (boot.go:27)   ADDQ    $136, SP
    0x020d 00525 (boot.go:27)   RET
    0x020e 00526 (boot.go:20)   XCHGL   AX, AX
    0x020f 00527 (boot.go:20)   CALL    runtime.deferreturn(SB)
    0x0214 00532 (boot.go:20)   MOVQ    128(SP), BP
    0x021c 00540 (boot.go:20)   ADDQ    $136, SP
    0x0223 00547 (boot.go:20)   RET
    0x0224 00548 (boot.go:18)   XCHGL   AX, AX
    0x0225 00549 (boot.go:18)   CALL    runtime.deferreturn(SB)
    0x022a 00554 (boot.go:18)   MOVQ    128(SP), BP
    0x0232 00562 (boot.go:18)   ADDQ    $136, SP
    0x0239 00569 (boot.go:18)   RET
    0x023a 00570 (boot.go:17)   XCHGL   AX, AX
    0x023b 00571 (boot.go:17)   CALL    runtime.deferreturn(SB)
    0x0240 00576 (boot.go:17)   MOVQ    128(SP), BP
    0x0248 00584 (boot.go:17)   ADDQ    $136, SP
    0x024f 00591 (boot.go:17)   RET
    0x0250 00592 (boot.go:16)   XCHGL   AX, AX
    0x0251 00593 (boot.go:16)   CALL    runtime.deferreturn(SB)
    0x0256 00598 (boot.go:16)   MOVQ    128(SP), BP
    0x025e 00606 (boot.go:16)   ADDQ    $136, SP
    0x0265 00613 (boot.go:16)   RET
    0x0266 00614 (boot.go:10)   XCHGL   AX, AX
    0x0267 00615 (boot.go:10)   CALL    runtime.deferreturn(SB)
    0x026c 00620 (boot.go:10)   MOVQ    128(SP), BP
    0x0274 00628 (boot.go:10)   ADDQ    $136, SP
    0x027b 00635 (boot.go:10)   RET
    0x027c 00636 (boot.go:10)   NOP
    0x027c 00636 (boot.go:5)    PCDATA  $0, $-1
    0x027c 00636 (boot.go:5)    PCDATA  $2, $-1
    0x027c 00636 (boot.go:5)    CALL    runtime.morestack_noctxt(SB)
    0x0281 00641 (boot.go:5)    JMP 0


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:godaner已被使用

查看原文:golang defer 的不同书写方式导致的差异

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

378 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传