Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is golang "defer" scoped to function, not lexical enclosure

Tags:

go

I was surprised to find that these two programs produce the same output:

Program A

package main
import "fmt"

func main() {  
    defer fmt.Println(1)
    defer fmt.Println(2)
}

Program B

package main
import "fmt"

func main() {  
    {
        defer fmt.Println(1)
    }
    defer fmt.Println(2)
}

In other words, the "defer" statement appears to disregard lexical closures [edit: Thanks to @twotwotwo for correcting my terminology, I meant to say "block" not "lexical closure"] and is strictly scoped to the function. I wondered:

  1. is my understanding correct?
  2. is there a way to scope it to the block so that it triggers upon exiting the closure, not the function?

I can imagine doing several units of work in sequence, each requiring its own resource to be closed before proceeding... would be nice not to have to break them into separate functions solely for that purpose.

like image 360
Magnus Avatar asked Mar 23 '18 19:03

Magnus


People also ask

What is the point of defer 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.

Is defer a Goroutine?

A deferred function call is a function call which follows a defer keyword. The defer keyword and the deferred function call together form a defer statement. Like goroutine function calls, all the results of the function call (if the called function has return results) must be discarded in the function call statement.

Is defer blocking Golang?

Defer is more like a finally block in languages like Java or Python: something that has to be executed after attempting to run some code – whether or not it succeeds. This is useful in cases where you have to run some clean-up operation after some code executes. For example: Closing a file after opening it.

Does defer run on panic Golang?

defer won't work after panic because the control never reached the statement, hence it was never registered. This is like printing something after a return statement in a function, it's basically an unreachable code.


1 Answers

  1. Is my understanding correct?

Yes.

  1. Is there a way to scope it to the block [...]?

There is no way to change how defer works. Depending on the problem you are trying to solve, perhaps splitting your function (example) or defining anonymous functions (example) would help. The latter just for reference and probably best avoided because of how it makes the code less readable.

More info on defer at Go Spec.

like image 171
jsageryd Avatar answered Sep 20 '22 12:09

jsageryd