This seems a bit stupid, surely theres a better way?
err = SendMessageAndWait(db, "this is a test")
if err != nil {
fmt.Println("Error sending message", err)
return
}
err = DoSomething(db, "this is a test")
if err != nil {
fmt.Println("Error sending message", err)
return
}
err = CheckSomething(db, "this is another test")
if err != nil {
fmt.Println("Error sending message", err)
return
}
err = SendMessageAndWait(db, "this is a third test")
if err != nil {
fmt.Println("Error sending message", err)
return
}
... x10 ...
Update: For the record, 5 years on from when I wrote this, I am now persuaded that this is a completely sufficient, and perhaps even better, way to handle errors clearly. Not saying its pretty though.
Sadly that's the way it is in Go, however in a way you can make it cleaner:
func isError(err error, pre string) error {
if err != nil {
log.Printf("%v: %v", pre, err)
}
return err
}
func isErrorBool(err error, pre string) (b bool) {
if err != nil {
log.Printf("%v: %v", pre, err)
b = true
}
return
}
func checkSomething() error {
return nil
}
func main() {
if err := isError(checkSomething(), "something failed"); err != nil {
return /* err */
}
//if you don't want to return the error, just check it and die.
if isErrorBool(checkSomething(), "something else failed") {
return
}
}
I would not just print an error and return nothing: the idea is to act on the error and return it (if no decisive action was taken, like a simple log).
Simply calling return
is like ignoring the error completely as far as the rest of the application is concerned.
See "Best Practices for Errors in Go", which includes advices as:
Given a small set of errors, the best way to handle this is to predefine each error publicly at the package level.
custom error type is the best solution to this problem. Go's implicit interfaces make creating one easy
package errgo provides the functionality of wrapping an error into another one that records where the error happened.
(You have the same features in dropbox/godropbox/errors/errors.go
)
In Go, always check for errors. For example,
package main
import "fmt"
func doStuff() error {
err := SendMessageAndWait(db, "this is a test")
if err != nil {
return err
}
err = DoSomething(db, "this is a test")
if err != nil {
return err
}
err = CheckSomething(db, "this is another test")
if err != nil {
return err
}
err = SendMessageAndWait(db, "this is a third test")
if err != nil {
return err
}
return nil
}
func main() {
err := doStuff()
if err != nil {
fmt.Println("Error sending message", err)
}
}
Given your lack of context, I can only assume you're returning from func main()
.
http://play.golang.org/p/pgcwMb647A
package main
import (
"fmt"
"log"
"errors"
)
func foo(x int) error {
if x == 3 {
return errors.New("x == 3")
}
fmt.Println(x)
return nil
}
func main() {
check := func(err error) {
if err != nil {
log.Fatal(err)
}
}
check(foo(1))
check(foo(2))
check(foo(3))
check(foo(4))
}
Generally, explicit handling is the way to go, but there's a variety of things you can do depending on the context.
At the risk of turning this into code golf, Go supports single line if statements with assignments in them:
if err := SendMessageAndWait(db, "this is a test"); err != nil {
return err
}
The downside is that all return values assigned are scoped to the corresponding if
/else if
/else
block, so if you actually need a different returned value outside that block, you have to go with something closer to PeterSO's answer.