Returning an error

suggest change

To indicate a failure, return a value of error type.

To indicate no error, return nil.

// somewhat inefficient way of appending a string at the end of a file
func appendToFile(path string, s string) error {
	d, err := ioutil.ReadFile(path)
  if err != nil {
		return err
  }
	d = append(d, []byte(s)...)
  return ioutil.WriteFile(path, d, 0644)
}

If the function also returns one or more values, error should be the last returned value:

func sqrt(n int) (int, error) {
	if n < 0 {
		return 0, fmt.Errorf("n should be >= 0, is %d", n)
	}
	return n*n, nil
}

Pitfalls

If you're using custom error types, don't return underlying type, always return error type.,

type CustomError struct {
}

func (e *CustomError) Error() string {
	return "this is a custom error"
}

func returnsCustomError(pleaseFail bool) *CustomError {
	if pleaseFail {
		return &CustomError{}
	}
	return nil
}

func caller() {
	var err error
	if err == nil {
		fmt.Printf("err is nil, as expected\n");
  }
	err = returnsCustomError(false))
	if err != nil {
		fmt.Printf("returnCustomError() failed with '%s'\n", err)
  }
}

Unexpectedly it looks like returnsCustomError() returned an error even though it returned nil.

This is a variant of nil interface pitfall.

#note link to that chapter

Uninitialized err value is nil because it's the zero value of interface types.

returnsCustomError() returns nil value of CustomError struct.

This nil value is assigned to err variable. This is equivalent to:

var err error
err = (*CustomError)(nil)

At this point err is no longer equal to zero value of interface type. It's value is *CustomError whose value is nil.

Therefore err no longer equals to nil.

To put it differently:

var err1 error
var err2 error = nil
var err3 error = (*CustomError)(nil)
if err1 == nil && err2 == nil {
	fmt.Printf("unitialized interface value and inteface value assigned nil are both zero values of interface type and therefore equal to 'nil'\n")
}
if err3 != nil {
	fmt.Printf("interface value assigned to a struct type whose value is nil is not zero value of interface type and therefore not equal to 'nil'\n")
}

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents