4 ms·
go's "defer" is like java/net "finally" for a try/catch enclosing the entire function. pro: you can push more than one "defer" in the same function. con: "fin
by lucio 9y ago
go's "defer" is like java/net "finally" for a try/catch enclosing the entire function.
pro: you can push more than one "defer" in the same function.
con: "finally" puts the cleanup code at the end of the function. With "defer" you have it scattered at the beginning.
- nothrabannosir 9y agocon: "finally" puts the cleanup code at the end of the function. With "defer" you have it scattered at the beginning. Quite commonly an advantage, e.g.: f, err := openFile('...') if err != nil { ... } defer f.Close() is how it's commonly used. This makes sense because the cleanup lives next to the initialization of the actual thing it's cleaning up. In a way it becomes part of the initialization, itself. Same with locks and release. Now you don't have to scan across the entire function body to make sure your inits and cleanups match up.
- albinofrenchy 9y agoThere is a substantial issue with this pattern for things like files -- the operating system imposes a max limit on the number of file descriptors you can have open. Defer gives no guarantees about when that thing is going to run -- just that it is after the function returns. Because of this, you can get erratic behavior if you open and defer closing a lot; essentially openFile just stops working at some point. This can happen with any limited resource and isn't theoretical; I had a friend who ran into this in long running process with a lot of IO.
- int_19h 9y agoIsn't it guaranteed to run at the exact point where the function in which "defer" was used returns?
- albinofrenchy 9y agoI was wrong, apparently it is. Really wish there was a way to edit that comment now.
- nothrabannosir 9y agoDefer statements run exactly at the moment of a function return (in lifo order). They are equivalent to wrapping the rest of the function body in a try / finally. They have to, since you can change the return value in a defer (by using named return values). A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking. https://golang.org/ref/spec#Defer_statements https://golang.org/ref/spec#Defer_statements There might have been something else going on with your friend's code. Maybe the function he was using didn't return before running out of file descriptors?
- albinofrenchy 9y agoI somehow completely misunderstood that from the Go documentation when first reading it; thank you for clarifying that. There must have been some other leaking going on. He was using a largish library when he saw the leak and eventual crash so maybe it was due to improper pooling or C api calls? I'll have to ask him more about it.
- karmakaze 9y ago> con: "finally" puts the cleanup code at the end of the function. With "defer" you have it scattered at the beginning. I would consider this a 'pro' as each action and defer are paired, executes in reverse order and a conditional action/defer doesn't need a second matching check.