Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why add "()" after closure body in Golang?

Tags:

closures

go

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.

like image 955
Reck Hou Avatar asked Apr 15 '13 06:04

Reck Hou


People also ask

How do closures work in Golang?

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.

Why do we need defer in Golang?

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.

Does Go supports function closer?

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.

What is defer in Golang?

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.

What is a closure function in Golang?

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

What is an anonymous function in Golang?

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.

How to create a closure of a 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.

What is closure property in go?

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.


2 Answers

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.

like image 117
zzzz Avatar answered Sep 26 '22 23:09

zzzz


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) 
like image 21
Erikas Avatar answered Sep 22 '22 23:09

Erikas