Errors

January 3, 2025

Today we’re looking at errors, and the built-in error interface. For a concept that’s so central to the Go ethos, the spec has surprisingly little to say about it:

Errors

The predeclared type error is defined as

type error interface {
	Error() string
}

It is the conventional interface for representing an error condition, with the nil value representing no error. For instance, a function to read data from a file might be defined:

func Read(f *File, b []byte) (n int, err error)

Why is there so little to say about errors in the spec?

Most of what we do with errors, isn’t “part of the language”. The only thing that really is baked into the language is the pre-declared type error. So that’s all we get here. 😊

Of course there’s a ton more that could be said about errors. And once we finish the spec (which is imminent now!), I’ll be happy to dive into such topics.

If you have any questions about errors, this is a great time to hit « REPLY » and let me know. I can start a backlog of interesting topics to discuss in the next week or two, when this spec series finishes up.


Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Error interfaces

On Monday I talked about error structs. Let’s continue that theme, with error interfaces. To recap the problem: You want to the caller of your function to be able to extract context from an error, without parsing error strings. Or maybe you even want to include context that isn’t part of the error string at all! Monday’s solution to this problem had us using custom structs. A similar, but often more flexible approach, is to use an error interface.


Error structs

The standard library gives us only very basic error capabilities. For the most part, we can create strings-as-errors: return errors.New("oh no") And we can wrap errors with additional textual context: if err := doSomething(); err != nil { return fmt.Errorf("doSomething: %w", err) } But the fact that the built-in error type is an interface gives us a ton more flexibility than this to include arbitrary information with our errors. There are a few ways we can include additional information in errors, and I’ll go over a few of them.


Constant errors

Last week I talked about how to create your own errors. Expanding on that idea, here’s a trick I like to use: Constant errors! Constants in Go are limited to simple underlying types: bool, string, and the numeric types. If we create our own type, which both satisfies the error interface, and has such an underlying type, we can then create constant error values: type errString string func (e errString) Error() string { return string(e) } const ErrTooManyFrogs = errString("too many frogs") Okay.

Get daily content like this in your inbox!

Subscribe