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

Reck Hou picture Reck Hou · Apr 15, 2013 · Viewed 26.9k times · Source

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.

Answer

zzzz picture zzzz · Apr 15, 2013

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.