首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >延迟和命名返回值是如何工作的?

延迟和命名返回值是如何工作的?
EN

Stack Overflow用户
提问于 2016-05-16 07:36:34
回答 3查看 34.4K关注 0票数 61

我刚开始学习Go,我被一个关于使用延迟更改Go博客-推迟,恐慌,和恢复中的命名返回值的例子搞混了。

这个例子说:

  1. 延迟函数可以读取并分配给返回函数的命名返回值。

在本例中,延迟函数在周围函数返回后增加返回值i。因此,此函数返回2

代码语言:javascript
运行
复制
func c() (i int) {
    defer func() { i++ }()
    return 1
}

但正如我从返回值的回访中学到的

不带参数的语句返回命名的返回值。这就是所谓的“赤裸”的回归。

我在下面的代码中进行了测试,在函数b中,它返回1,因为它不是上面提到的“无参数返回语句”的情况。

代码语言:javascript
运行
复制
func a() (i int) { // return 2
    i = 2
    return
}

func b() (i int) {  // return 1 
    i = 2
    return 1
}

所以我的问题是在第一个例子中,周围的函数c有一个命名的返回值i,但是函数c使用return 1,在第二个例子中,我们可以看到它应该有返回1,而不管i是什么值。但是,为什么在i更改了延迟函数之后,c函数返回i的值而不是值1?

当我键入问题时,我可能已经猜到了答案。是因为:

代码语言:javascript
运行
复制
return 1 

等于:

代码语言:javascript
运行
复制
i = 1
return 

在具有命名返回值变量i的函数中。

请帮我确认一下,谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-16 07:47:26

延迟语句将函数调用推入到列表中。保存的调用列表是在周围函数返回后执行的。-- Go博客:推迟,恐慌,恢复

理解上述陈述的另一种方式:

延迟语句将函数调用推送到堆栈上。保存的调用堆栈弹出(LIFO)和延迟函数将在周围函数返回之前立即调用。

代码语言:javascript
运行
复制
 func c() (i int) {
    defer func() { i++ }()
    return 1
}

返回1之后,将执行延迟func() { i++ }()。因此,按处决顺序:

  1. I=1(返回1)
  2. i++ (延迟函数从堆栈中弹出并执行)
  3. I == 2(命名变量I的最终结果)

为了理解:

代码语言:javascript
运行
复制
 func c() (i int) {
    defer func() { fmt.Println("third") }()
    defer func() { fmt.Println("second") }()
    defer func() { fmt.Println("first") }()

    return 1
}

处决令:

  1. I=1(返回1)
  2. “先”
  3. “第二”
  4. “第三”
票数 59
EN

Stack Overflow用户

发布于 2016-05-16 10:47:34

根据Go规范:

返回语句 --一条“返回”语句,指定在执行任何延迟函数之前设置结果参数。

延迟陈述“在周围函数返回之前立即调用...deferred函数.”

所以是的,正如您假设的那样,指定了指定的返回变量,然后延迟语句会增加它。

我想补充的是,命名的返回参数可能会导致细微的错误,并且通常应该避免,除非没有其他选择。

票数 12
EN

Stack Overflow用户

发布于 2017-03-16 10:49:24

我认为混淆是关于函数的,如果你这样分类的话:

代码语言:javascript
运行
复制
  func main() {
      fmt.Println(c()) //the result is 5
  }

  // the c function returned value is named j
  func c() (j int)  {
      defer changei(&j)
      return 6
  }
  func changei(j *int) {
      //now j is 6 because it was assigned by return statement 
      // and if i change guess what?! i changed the returned value
      *j--;
  }

但是,如果返回值不是这样命名的:

代码语言:javascript
运行
复制
  func main() {
      fmt.Println(c()) //the result will become 6
  }

  // the c function returned value is not named at this time
  func c() int  {
      j := 1
      defer changei(&j)
      return 6
  }
  func changei(j *int) {
      //now j = 1
      // and if i change guess what?! it will not effects the returned value
      *j--;
  }

我希望这能消除混乱,这就是我如何快乐地编码。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37248898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档