Created
November 6, 2018 02:00
-
-
Save cirocosta/d0b9cde1c79cc12a943a562a98ffd962 to your computer and use it in GitHub Desktop.
Capturing errors on a deferred statement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"os" | |
"code.cloudfoundry.org/lager" | |
) | |
// methodThatFails simply always fails, returning an | |
// error every time (after logging its execution). | |
func methodThatFails(logger lager.Logger) (err error) { | |
logger.Debug("method-that-fails") | |
err = fmt.Errorf("method-that-fails") | |
return | |
} | |
// method2 implements does the same as `method1`, except | |
// for the fact that it captures the error before returning. | |
// | |
// Once executed, although `methodThatFails` always fails, we | |
// see the following logs: | |
// | |
// DEBUG: start | |
// ERROR: fail: err=method-that-fails | |
// | |
func method2(logger lager.Logger) (err error) { | |
sess := logger.Session("method2") | |
sess.Debug("start") | |
defer func() { | |
if err != nil { | |
// By always assigning to `err` before | |
// returning, we make sure that the variable | |
// `err` gets properly set. | |
// | |
// Given that this `defer` gets called before | |
// we end the execution of this method, we have | |
// the behavior we expect. | |
sess.Error("fail", err) | |
return | |
} | |
sess.Debug("finished") | |
}() | |
err = methodThatFails(sess) | |
return | |
} | |
// method1 implements a defer statement that "feels like" | |
// it does the right thing (capturing the error before exiting), | |
// except that it doesn't. | |
// | |
// Once executed, although `methodThatFails` always fails, we | |
// see the following logs: | |
// | |
// DEBUG: start | |
// DEBUG: finished | |
// | |
func method1(logger lager.Logger) error { | |
var ( | |
err error | |
sess = logger.Session("session") | |
) | |
sess.Debug("start") | |
defer func() { | |
if err != nil { | |
// Won't *EVER* reach this branch given that | |
// we're never setting `err` to the value of | |
// the error before returning. | |
sess.Error("fail", err) | |
return | |
} | |
sess.Debug("finished") | |
}() | |
return methodThatFails(sess) | |
} | |
func main() { | |
logger := lager.NewLogger("main") | |
logger.RegisterSink(lager.NewWriterSink(os.Stdout, lager.DEBUG)) | |
method1(logger) | |
method2(logger) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment