Go functions commonly return an error value next to the useful result.

error return A nil error means the operation succeeded; a non-nil error describes what went wrong.

Error Return Values

parts
error_return.go
Replay: real traced execution (multi-file project)
package main

import (
	"errors"
	"fmt"
)

func divide(total int, parts int) (int, error) {
	if parts == 0 {
		return 0, errors.New("parts cannot be zero")
	}
	return total / parts, nil
}

func main() {
	var parts = 4
	result, err := divide(20, parts)

	if err != nil {
		fmt.Println("error=", err)
	} else {
		fmt.Println("result=", result)
	}
}
package main

import (
	"errors"
	"fmt"
)

func divide(total int, parts int) (int, error) {
	if parts == 0 {
		return 0, errors.New("parts cannot be zero")
	}
	return total / parts, nil
}

func main() {
	var parts = 0
	result, err := divide(20, parts)

	if err != nil {
		fmt.Println("error=", err)
	} else {
		fmt.Println("result=", result)
	}
}
package main

import (
	"errors"
	"fmt"
)

func divide(total int, parts int) (int, error) {
	if parts == 0 {
		return 0, errors.New("parts cannot be zero")
	}
	return total / parts, nil
}

func main() {
	var parts = 5
	result, err := divide(20, parts)

	if err != nil {
		fmt.Println("error=", err)
	} else {
		fmt.Println("result=", result)
	}
}
  1. parts ← 4

    15func main() {16  var parts→ 4 = 4 //@parts=0, 517  result, err := divide(20, parts4)
  2. func divide(total int, parts int) (int, error)

    8func divide(total20 int, parts4 int) (int, error) {9  if parts == 0 {10    return 0, errors.New("parts cannot be zero")11  }12  return total20 / parts4, nil13}
  3. result ← 5, err ← <nil>

    16var parts = 4 //@parts=0, 517result→ 5, err→ <nil> := divide(20, parts4)
  4. else

    20  fmt.Println("error=", err)21} else {22  fmt.Println("result=", result5)23}
    outputresult= 5
  1. parts ← 0

    15func main() {16  var parts→ 0 = 017  result, err := divide(20, parts0)
  2. func divide(total int, parts int) (int, error)

    8func divide(total20 int, parts0 int) (int, error) {9  if parts == 0 {
  3. if parts == 0

    8func divide(total int, parts int) (int, error) {9  if parts0 == 0 {10    return 0, errors.New("parts cannot be zero")11  }
  4. result ← 0, err ← &errors.errorString{s:"parts cannot be zero"}

    16var parts = 017result→ 0, err→ &errors.errorString{s:"parts cannot be zero"} := divide(20, parts0)
  5. if err != nil

    19if err&errors.errorString{s:"parts cannot be zero"} != nil {20  fmt.Println("error=", err&errors.errorString{s:"parts cannot be zero"})21} else {
    outputerror= parts cannot be zero
  1. parts ← 5

    15func main() {16  var parts→ 5 = 517  result, err := divide(20, parts5)
  2. func divide(total int, parts int) (int, error)

    8func divide(total20 int, parts5 int) (int, error) {9  if parts == 0 {10    return 0, errors.New("parts cannot be zero")11  }12  return total20 / parts5, nil13}
  3. result ← 4, err ← <nil>

    16var parts = 517result→ 4, err→ <nil> := divide(20, parts5)
  4. else

    20  fmt.Println("error=", err)21} else {22  fmt.Println("result=", result4)23}
    outputresult= 4

Follow the Error Check

  1. divide returns a number and an error.
  2. When parts is not zero, the error is nil.
  3. When parts is zero, the error is non-nil.
  4. The caller checks err before using the result. | err value | Branch | | --- | --- | | nil | print result | | non-nil | print error |

Exercise: error_return.go

Return an error when dividing by zero, then branch on nil versus non-nil error