为什么Go语言的“defer”作用域是函数,而不是词法封装?

bkhjykvo  于 2023-06-27  发布在  Go
关注(0)|答案(2)|浏览(89)

我惊讶地发现这两个程序产生相同的输出:

方案A

package main
import "fmt"

func main() {  
    defer fmt.Println(1)
    defer fmt.Println(2)
}  //prints 2 1

方案B

package main
import "fmt"

func main() {  
    {
        defer fmt.Println(1)
    }
    defer fmt.Println(2)
}  //prints 2 1

换句话说,“defer”语句似乎忽略了词法闭包[edit:感谢@ twotwetwo纠正了我的术语,我的意思是说“块”而不是“词法闭包”],并且严格限制在函数的范围内。我想知道:
1.我的理解是否正确?
1.有没有一种方法可以将它的范围限定在块上,这样它就可以在退出闭包时触发,而不是在退出函数时触发?
我可以想象按顺序执行几个工作单元,每个单元都需要在继续之前关闭自己的资源……如果不是为了那个目的而把它们分解成单独的函数就好了。

vc9ivgsu

vc9ivgsu1#

1.我的理解是否正确?
是的
1.有没有办法把它的范围扩大到块[...]?
没有办法改变defer的工作方式。根据您试图解决的问题,拆分函数(example)或定义匿名函数(example)可能会有所帮助。后者仅供参考,可能最好避免,因为它使代码可读性降低。
更多关于defer的信息,请访问Go Spec.

ttvkxqim

ttvkxqim2#

是否正确?

是的

为什么?

如果你只能有一个行为,功能与块,哪一个更容易定义另一个?

  • 假设defer在块上工作。如果你想在更大的范围内,你不能。有时候,Go需要你输入一个新的块,就像在if语句中一样,这使得在应用defer时很难控制。
  • 现在,如果defer的作用域是函数,那么您可以轻松地添加一个新函数来缩小作用域。你甚至可以有一个你直接调用的匿名函数。
func() {
    defer ...
}()

相关问题