Sage-Code Laboratory
index<--

Go Errors

One Go program can execute normally or can have errors. Go programs create error state with "error" values. Functions often return a value of type "error". Calling code that may fail should handle errors by testing whether the "error" is nil.

The error type is a built-in interface similar to fmt.Stringer. You can implement any struct that implements this interface and you have a kind of error.

type error interface {
    Error() string
}

As with fmt.stringer the fmt package looks for the error interface when printing values. In next fragment we demonstrate an error.

i, err := strconv.Atoi("42")
if err != nil {
    fmt.Printf("couldn't convert number: %v\n", err)
    return
}
fmt.Println("Converted integer:", i)

Example:

A nil error denotes success; a non-nil error denotes failure. In next example we define a user error and we customize the error function:

//file error_hnd.go
package main

import (
    "fmt"
    "time"
)

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

Panic statement

We use "panic" keyword to intrerupt the program. Typically it means something went unexpectedly wrong. Mostly we use it to fail fast on errors that shouldn't occur during normal operation.


package main

import "os"

func main() {
    // how to panic
    panic("a problem")

    // handle error using panic
    _, err := os.Create("/tmp/file")
    if err != nil {
        panic(err)
    }
}

Recovering

Function recover() is provided for error handling. It must be called within a a defer function. When the enclosing function panics, the defer will activate and a recover() call within it will catch the panic error message and report it.


package funcs

import "fmt"

func TestRecover() {
    fmt.Println("protect this function")

    // create an anonymous function
    defer func() {
        if e := recover(); e != nil {
            // The return value of recover() is the error
            fmt.Println("Recovered from: ", e)
        }
    }()

    fmt.Println("get ready for panic")

    // create an error on purpose
    fmt.Println("paniking ...")
    panic("My error")

    // Next print will not run
    fmt.Println("This is not executed.")
}

Exit status

Go exit with return 0 from main() function. You can use os.Exit() in main() or in any other function to exit from application with a different status.


package demo

import (
   "fmt"
   "os"
)

func DemoExit() {
   // expect ths to print
   fmt.Println("exiting ...")

   // is this going to be print?
   defer fmt.Println("done !")

   os.Exit(3) // error
}

Output:

exiting ...
make: *** [Makefile:3: run] Error 3
exit status 2

Read next: Files & Folders