Essential Go Error handling  Suggest an edit

Handling errors in short programs

Propagating errors up to the callers is tedious. You end up with many lines looking like:

r, err := os.Open("my file")
if err != nil {
    return err
}

This kind of error handling diligence is crucial for writing robust software.

Sometimes you write shorter cmd-line programs where such discipline is not warranted.

You can simplify error handling with a helper functions PanicIfErr(err error, args ...interface{}):

r, err := os.Open("my file")
PanicIfErr(err)

Implementation of such helper:

// FmtArgs formats args as a string. First argument should be format string
// and the rest are arguments to the format
func FmtArgs(args ...interface{}) string {
	if len(args) == 0 {
		return ""
	}
	format := args[0].(string)
	if len(args) == 1 {
		return format
	}
	return fmt.Sprintf(format, args[1:]...)
}

func panicWithMsg(defaultMsg string, args ...interface{}) {
	s := FmtArgs(args...)
	if s == "" {
		s = defaultMsg
	}
	fmt.Printf("%s\n", s)
	panic(s)
}

// PanicIf panics if cond is true
func PanicIf(cond bool, args ...interface{}) {
	if !cond {
		return
	}
	panicWithMsg("PanicIf: condition failed", args...)
}

// PanicIfErr panics if err is not nil
func PanicIfErr(err error, args ...interface{}) {
	if err == nil {
		return
	}
	panicWithMsg(err.Error(), args...)
}

func main() {
	PanicIfErr(nil)                              // nothing happens
	PanicIfErr(errors.New("there was an error")) // will panic
}
there was an error
panic: there was an error

goroutine 1 [running]:
main.panicWithMsg(0x10c5834, 0x12, 0x0, 0x0, 0x0)
	/private/var/folders/2k/p2_4052s70vd5_cfdm0k0l740000gn/T/src703135489/main.go:29 +0x144
main.PanicIfErr(0x10d8a80, 0xc00009c030, 0x0, 0x0, 0x0)
	/private/var/folders/2k/p2_4052s70vd5_cfdm0k0l740000gn/T/src703135489/main.go:45 +0x6c
main.main()
	/private/var/folders/2k/p2_4052s70vd5_cfdm0k0l740000gn/T/src703135489/main.go:50 +0x91
exit status 2

  ↑ ↓ to navigate     ↵ to select     Esc to close