I'm reading The Go Programming Language Specifications
and found myself not truly understand with "()" after closure body:
In Function literals
:
func(ch chan int) { ch <- ACK }(replyChan)`
In Defer statements
's example:
// f returns 1
func f() (result int) {
defer func() {
result++
}() // why and how?
return 0
}
I'm not clear about the reason to add & usage of "()" after closure body, hope someone can explain this clearly.
It's not that
()
must be added after (only) a closure indefer
. The language specs for the defer statement mandate that its 'Expression' always must be a function call.And why is it so? It's the same as with any other function, in 'defer' or not:
Consider:
and
vs
The first expression RHS is a function value. In the second version the RHS is the value returned by the function - i.e. a function call.
So is the semantics of:
vs
except that the first version doesn't make sense in the context of 'defer', and so the specifications mention that it must be the second form (only).
It's IMHO also easier to learn because of the orthogonality with the above discussed function call outside of the 'defer' statement.
Also note that a function call is not only fn-expr followed by
()
, but an expression list is generally inside the parenthesis (including an empty list). There's a big difference between:and
The first version prints the value of 'i' in the moment when the closure executes, the second prints the value of 'i' in the moment when the defer statement was executed.
Since you are still confused, here's another attempt to provide an answer to your question.
In the context of your question,
()
is the function invocation operator.For example, the function literal
represents an anonymous function.
The function literal followed by the
()
function invocation operatorrepresents an anonymous function which is then invoked directly.
Ordinarily, in a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the calling function when the function returns.
However, invoking the function through the defer statement is a special case. Each time the "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked. Instead, deferred calls are executed in LIFO order immediately before the surrounding function returns, after the return values, if any, have been evaluated, but before they are returned to the caller.
The defer statement expression must be a function or method call that is invoked directly, not just a function or method literal which is not invoked directly. Therefore, the function or method literal needs to be followed by the
()
function invocation operator so that the defer statement expression is a function or method call.The defer statement
is valid.
The defer statement
is invalid:
syntax error: argument to go/defer must be function call
.