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 韩国网站购物,KG支付的支付回调如何解决
  • ¥15 workstation导入ovf文件,报错,怎么解决呢?
  • ¥15 关于#c语言#的问题:构成555单稳态触发器,采用LED指示灯延时时间,对延时时间进行测量并显示(如楼道声控延时灯)需要Proteus仿真图和C语言代码
  • ¥15 workstation加载centos进入emergency模式,查看日志报警如图,怎样解决呢?
  • ¥50 如何用单纯形法寻优不能精准找不到给定的参数,并联机构误差识别,给定误差有7个?matlab
  • ¥15 workstation加载centos进入emergency模式,查看日志报警如图,没有XFS,怎样解决呢?
  • ¥15 应用商店如何检测在架应用内容是否违规?
  • ¥15 Ubuntu系统配置PX4
  • ¥50 nw.js调用activex
  • ¥15 数据库获取信息反馈出错,直接查询了ref字段并且还使用了User文档的_id而不是自己的