4 回答
TA贡献1786条经验 获得超13个赞
这并不是说()必须(仅)一个后添加封在defer。defer 语句的语言规范要求其“表达式”始终必须是函数调用。
为什么会这样?它与任何其他函数相同,无论是否“延迟”:
考虑:
func f() int { return 42 }
和
a := f
对比
b := f()
第一个表达式 RHS 是一个函数值。在第二个版本中,RHS 是函数返回的值——即函数调用。
语义也是如此:
defer f
对比
defer f()
除了第一个版本在“延迟”的上下文中没有意义,因此规范提到它必须是第二种形式(仅)。
恕我直言,由于与“延迟”语句之外的上述函数调用的正交性,因此也更容易学习。
另请注意,函数调用不仅是 fn-expr 后跟(),而且表达式列表通常位于括号内(包括空列表)。之间有很大的区别:
for i := range whatever {
defer func() { fmt. Println(i) }()
}
和
for i := range whatever {
defer func(n int) { fmt. Println(n) }(i)
}
关闭时,第一个版本在当下打印的“我”的值执行,第二打印“我”在当下的价值时,defer语句被执行。
TA贡献1943条经验 获得超7个赞
参考
函数类型表示具有相同参数和结果类型的所有函数的集合。
FunctionType = "func" Signature .Signature = Parameters [ Result ] .Result = Parameters | Type .Parameters = "(" [ ParameterList [ "," ] ] ")" .ParameterList = ParameterDecl { "," ParameterDecl } .ParameterDecl = [ IdentifierList ] [ "..." ] Type .函数声明将标识符(函数名称)绑定到函数。
FunctionDecl = "func" FunctionName Signature [ Body ] .FunctionName = identifier .Body = Block .函数文字表示匿名函数。它由函数类型的规范和函数体组成。
FunctionLit = FunctionType Body .函数字面量是闭包:它们可以引用在周围函数中定义的变量。然后这些变量在周围的函数和函数字面量之间共享,只要它们可访问,它们就会存在。
函数文字可以分配给变量或直接调用。
给定一个
f
函数类型的表达式F
,f(a1, a2, … an)
f
带参数的调用a1, a2, … an
。在函数调用中,函数值和参数按通常的顺序计算。在对它们求值后,调用的参数按值传递给函数,被调用的函数开始执行。当函数返回时,函数的返回参数按值传递回调用函数。
"
defer
" 语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻。DeferStmt = "defer" Expression .表达式必须是函数或方法调用。每次“
defer
”语句执行时,函数值和调用的参数都会像往常一样被评估并重新保存,但不会调用实际的函数。相反,延迟调用在周围函数返回之前立即以 LIFO 顺序执行,在返回值(如果有)被评估之后,但在它们返回给调用者之前。
由于您仍然感到困惑,这是为您的问题提供答案的另一种尝试。
在您的问题的上下文中,()
是函数调用运算符。
例如,函数字面量
func(i int) int { return 42 * i }
表示匿名函数。
函数文字后跟()
函数调用运算符
func(i int) int { return 42 * i }(7)
表示一个匿名函数,然后直接调用该函数。
通常,在函数调用中,函数值和参数按通常的顺序计算。在对它们求值后,调用的参数按值传递给函数,被调用的函数开始执行。当函数返回时,函数的返回参数按值传递回调用函数。
但是,通过 defer 语句调用函数是一种特殊情况。每次执行“defer”语句时,函数值和调用的参数都会像往常一样评估并重新保存,但不会调用实际的函数。相反,延迟调用在周围函数返回之前立即以 LIFO 顺序执行,在返回值(如果有)被评估之后,但在它们返回给调用者之前。
defer 语句表达式必须是直接调用的函数或方法调用,而不仅仅是未直接调用的函数或方法文字。因此,函数或方法字面量后面需要跟()
函数调用运算符,这样 defer 语句表达式就是函数或方法调用。
延迟声明
defer func(i int) int { return 42 * i }(7)
已验证。
延迟声明
defer func(i int) int { return 42 * i }
无效:syntax error: argument to go/defer must be function call
。
- 4 回答
- 0 关注
- 373 浏览
添加回答
举报