Creating errors

February 3, 2025

Just over a year ago I started this (mostly) daily mailing list, with the goal of going through the entire Go spec, to make it easier for you (and me!) to understand.

That mission ended on Friday.

So starting today, this list will take on a less structured format. I’ll still be talking about Go. And whenever the spec is updated (as is due to happen any day now, once Go 1.24 is officially released), I’ll revisit the spec to explain what’s new.

But for now, I want to answer a couple reader questsions. I asked for these a few weeks ago, and they’re still welcome. If something bothers you about Go, or just doesn’t make sense, hit that « REPLY » button, and let me know. I’ll try to address it here. And maye also in an upcoming video (I hope to get back into making videos next month, as I should be back into a normal office/studio by then).

For today, the question I want to answer is:

I would like to ask about fmt.Errorf. How is that function able to coerce a string into an error? Is it possible for an end user to type cast a string into an error directly?

To answer this question, the first thing we need is a refresher on what an error in Go even is! Let’s refresh our memory by looking at the relevant section of the spec:

Errors

The predeclared type error is defined as

type error interface {
	Error() string
}

So that’s really it. An error, in Go, is any value which satifies that interface.

So is it possible for an end user to convert a string into an error directly? Yes. It’s quite trivial. All you need to do is create a type that implements that interface:

type MyError string

func (e MyError) Error() string {
  return string(e)
}

That’s it!

Now MyError satisfies the error interface.

So how does fmt.Errorf return an error? It does the same exact trick. We can look at the source code to see exactly what it does:

func Errorf(format string, a ...any) error {
	/* .. snip .. */
		w := &wrapError{msg: s}
		w.err, _ = a[p.wrappedErrs[0]].(error)
		err = w
	/* .. snip .. */
	return err
}

There’s much more in that function, but we’re only looking at part of it here, for explanatory purposes. In essence, it reutrns avalue of type *wrapError. So let’s look at that type:

type wrapError struct {
	msg string
	err error
}

func (e *wrapError) Error() string {
	return e.msg
}

And there you have it. fmt.Errorf returns a *wrapError value which implements the error interface by virtue of having an Error() string method on it.


Share this

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

Unsure? Browse the archive .

Related Content


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.


100 episodes of Cup o' Go!

Yesterday, Shay Nehmad and I, and close to 20 other people, recorded the 100th episode of the Cup o’ Go podcast. It’s been just over two years since the first episode came out, and in that time we’ve made some good friends, and built a bit of a community. If you haven’t listened yet, I invite you to listen to the replay of the live episode, which is also about celebrating the newly released Go 1.


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