猿问

关于延迟行为的 Go 语言面试问题

我有 2 个代码示例:


func test() int {

    var x int

    defer func() {


        x++

    }()

    x = 1

    return x

}


func main() {

    fmt.Println(test())

}

它返回:1。但是,以下代码示例的行为有所不同:


func test() (x int) {

    defer func() {


        x++

    }()

    x = 1

    return

}


func main() {

    fmt.Println(test())

}

它返回2。


为了了解发生了什么,我反汇编了代码。

对于第一个代码片段(其输出为1):


  main.go:19            0x48cf40                64488b0c25f8ffffff      MOVQ FS:0xfffffff8, CX

  main.go:19            0x48cf49                483b6110                CMPQ 0x10(CX), SP

  main.go:19            0x48cf4d                7678                    JBE 0x48cfc7

  main.go:19            0x48cf4f                4883ec58                SUBQ $0x58, SP

  main.go:19            0x48cf53                48896c2450              MOVQ BP, 0x50(SP)

  main.go:19            0x48cf58                488d6c2450              LEAQ 0x50(SP), BP

  main.go:20            0x48cf5d                e83effffff              CALL main.test(SB)

  main.go:20            0x48cf62                e8c9bff7ff              CALL runtime.convT64(SB)

  main.go:20            0x48cf67                488b442408              MOVQ 0x8(SP), AX

  main.go:20            0x48cf6c                0f57c0                  XORPS X0, X0

  main.go:20            0x48cf6f                0f11442440              MOVUPS X0, 0x40(SP)


小怪兽爱吃肉
浏览 176回答 1
1回答

梵蒂冈之花

Golang 规范对 defer 语句这样说:[...] 如果延迟函数是函数字面量,并且周围的函数具有在字面量范围内的命名结果参数,则延迟函数可以在返回结果参数之前访问和修改结果参数。(我的重点)在您的第一个片段中,函数test没有命名返回参数;x只是一个局部变量。因此,您的 defer 语句不能修改 function 的结果test。在您的第二个片段中,函数test有一个命名的返回参数x,它在您的函数文字范围内。因此, defer 语句可以(并且确实)修改了 function 的结果test。
随时随地看视频慕课网APP

相关分类

Go
我要回答