Go The Error Interface
The error type is an interface with one method named Error. That method returns the problem as a string.
An error value starts as nil
A variable of the error type starts as nil. The code then stores an error built with errors.New.
package main
import (
"errors"
"fmt"
)
func main() {
var err error
fmt.Println(err == nil)
err = errors.New("disk full")
fmt.Println(err)
}A custom error from a function
LimitError stores the limit and the value that broke it. Its Error method returns a fixed message.
package main
import "fmt"
type LimitError struct {
Limit int
Value int
}
func (e LimitError) Error() string {
return "value is over the limit"
}
func checkValue(v int) error {
if v > 10 {
return LimitError{Limit: 10, Value: v}
}
return nil
}
func main() {
err := checkValue(14)
fmt.Println(err)
}Value receivers and pointer receivers
EmptyError has a value receiver on Error. RangeError has a pointer receiver on Error. The prints show a value and a pointer for the first type, and a pointer for the second type.
package main
import "fmt"
type EmptyError struct{}
func (e EmptyError) Error() string {
return "value is empty"
}
type RangeError struct{}
func (e *RangeError) Error() string {
return "value is out of range"
}
func main() {
var first error = EmptyError{}
var second error = &EmptyError{}
var third error = &RangeError{}
fmt.Println(first)
fmt.Println(second)
fmt.Println(third)
}Field values inside the message
fmt.Sprintf builds a string from a pattern and values. The Error method of SizeError fills %d with each stored number.
package main
import "fmt"
type SizeError struct {
Got int
Max int
}
func (e SizeError) Error() string {
return fmt.Sprintf("size %d is over the max %d", e.Got, e.Max)
}
func main() {
var err error = SizeError{Got: 25, Max: 20}
fmt.Println(err)
}Example
package main
import "fmt"
type FieldError struct {
Field string
Value int
}
func (e FieldError) Error() string {
return fmt.Sprintf("%s value %d is not allowed", e.Field, e.Value)
}
func checkScore(score int) error {
if score < 0 {
return FieldError{Field: "score", Value: score}
}
if score > 100 {
return FieldError{Field: "score", Value: score}
}
return nil
}
func main() {
fmt.Println(checkScore(-5))
fmt.Println(checkScore(140))
}Key points
- The error interface names the method Error() string.
- A custom error type is a type that gives itself an Error method.
- A struct error type can store fields that describe the problem.
- The Error method can build its message from the stored fields.
- A value receiver on Error lets a value and a pointer both serve as errors.
- A pointer receiver on Error lets only a pointer serve as an error.
In this example, FieldError stores the name of a field and its bad value. Its Error method builds a message from both stored values. checkScore returns a FieldError when a score is below zero or above 100. Main prints the errors for -5 and 140.
Note
Printing an error value prints the string its Error method returns.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Go Playground
Exercise
Which method must a type have so its values can serve as errors?