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.
In Golang, a closure is a function that references variables outside of its scope. A closure can outlive the scope in which it was created. Thus it can access variables within that scope, even after the scope is destroyed. Before diving deeper into closures, you need to understand what is an anonymous function.
In Go language, defer statements delay the execution of the function or method or an anonymous method until the nearby functions returns. In other words, defer function or method call arguments evaluate instantly, but they don't execute until the nearby functions returns.
Go supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.
In Golang, the defer keyword is used to delay the execution of a function or a statement until the nearby function returns. In simple words, defer will move the execution of the statement to the very end inside a function.
A closure is a function inside another function “closes over” one or more local variables of the outer function. Golang supports nested functions. A nested function is a function that is defined inside another function. A closure involves a function that uses variables from another function scope
Go language provides a special feature known as an anonymous function. An anonymous function can form a closure. A closure is a special type of anonymous function that references variables declared outside of the function itself. It is similar to accessing global variables which are available before the declaration of the function.
The closure can be created when an anonymous function is declared. That function has access to its surrounding state and its state becomes unique. The code above has created a closure of the function f containing i.
This property is called the closure property. What is Closure in GoLang? Closure occurs when an anonymous function in Go has access to its surroundings. Then it can hold a unique state of its own. The state then becomes isolated as we create new instances of the function. The closure can be created when an anonymous function is declared.
It's not that ()
must be added after (only) a closure in defer
. 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:
func f() int { return 42 }
and
a := f
vs
b := f()
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:
defer f
vs
defer f()
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:
for i := range whatever { defer func() { fmt. Println(i) }() }
and
for i := range whatever { defer func(n int) { fmt. Println(n) }(i) }
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.
If you don't want to read long answers:
str := "Alice" go func(name string) { fmt.Println("Your name is", name) }(str)
Is same as:
str := "Alice" f := func(name string) { fmt.Println("Your name is", name) } go f(str)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With