Errors
Handle errors in Go
Check function
Save yourself doing 3-line checks for err != nil
all over and use a check
function,
func check(e error) {
if e != nil {
panic(e)
}
}
Usage:
f, err := os.Open("/tmp/foo.txt")
check(err)
Panic
From Effective Go.
real library functions should avoid panic.
If the problem can be masked or worked around, it’s always better to let things continue to run rather than taking down the whole program. One possible counterexample is during initialization: if the library truly cannot set itself up, it might be reasonable to panic, so to speak.
var user = os.Getenv("USER")
func init() {
if user == "" {
panic("no value for $USER")
}
}
Recover
recover is only useful inside deferred functions.
One application of recover is to shut down a failing goroutine inside a server without killing the other executing goroutines.
func server(workChan <-chan *Work) {
for work := range workChan {
go safelyDo(work)
}
}
func safelyDo(work *Work) {
defer func() {
if err := recover(); err != nil {
log.Println("work failed:", err)
}
}()
do(work)
}
In this example, if
do(work)
panics, the result will be logged and the goroutine will exit cleanly without disturbing the others. There’s no need to do anything else in the deferred closure; calling recover handles the condition completely.
Printing errors
Based on StackCheck tool’s message.
$ staticcheck -explain ST1005
Error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation, since they are usually printed following other context…
So use this:
fmt.Errorf("something bad")
Not this:
fmt.Errorf("Something bad")
Such that this formats without a spurious capital letter mid-message.
log.Printf("Reading %s: %v", filename, err)