douruanfan3030 2019-05-02 10:37
浏览 34
已采纳

为什么在以下带有defer的golang代码示例中得到0和1

Call to defer produces different results for variables declared in two different ways

package main

import (
    "fmt"
)

func c(i int) int {
    defer func() { i++ }()
    return i
}

func c1() (i int) {
    defer func() { i++ }()
    return i
}

func c2() (i int) {
    defer func() { i++ }()
    return 2
}

func main() {
    fmt.Println(c(0)) // Prints 0
    fmt.Println(c1()) // Prints 1
    fmt.Println(c2()) // Prints 3 Thank you icza
}

https://play.golang.org/p/gfnnCZ--DkH

  • 写回答

1条回答 默认 最新

  • douzuo5504 2019-05-02 10:51
    关注

    In the first example i is an (incoming) parameter. At the return statement the return value is evaluated, and the deferred function runs after this, and incrementing i in that has no effect on the return value.

    In the second example i is the name of the result parameter. At the return statement you explicitly return the value i, which is then assigned to the return value i (this is a no-op). But deferred functions are allowed to modify the values of the return "variables", and if they do so, that will have an effect on the actual returned values.

    This becomes clearer if we add another example:

    func c2() (i int) {
        defer func() { i++ }()
        return 2
    }
    

    This function will return 3, because the return 2 statement will assign 2 to i, then the deferred function will increment this, and so the return value will be 3. Try this one on the Go Playground. Relevant part from the Spec: Return statements:

    A "return" statement that specifies results sets the result parameters before any deferred functions are executed.

    In general, if a function (or method) has named result parameters, the return values will always be the values of those variables, but must not forget that a return statement may assign new values to these result paramteters, and they may be modified by deferred functions after a return statement.

    This is mentioned in the Spec: Defer statements:

    For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned.

    It is also mentioned in the blog post Defer, Panic and Recover:

    Deferred functions may read and assign to the returning function's named return values.

    And also in Effective Go: Recover:

    If doParse panics, the recovery block will set the return value to nil—deferred functions can modify named return values.

    See related question: How to return a value in a Go function that panics?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!