Skip to content

blog: unintuitive code in errors post example #35361

Closed
@kevinburke1

Description

@kevinburke1

I am reading about how to use the new Go errors code. In this blog post, there's the following example:

// The As function tests whether an error is a specific type.

// Similar to:
//   if e, ok := err.(*QueryError); ok { … }
var e *QueryError
if errors.As(err, &e) {
    // err is a *QueryError, and e is set to the error's value
}

My initial read was that this can't be right - it's taking the address of a *QueryError, which gives a **QueryError, which a) does not match the type of the "Similar to" immediately above it, and b) a pointer to a pointer is almost never what you want in Go.

However I wrote some tests and yeah a **QueryError is actually what we want here:

type QueryError struct{}

func (e *QueryError) Error() string {
	return "an error occurred"
}

func TestErrorsAs(t *testing.T) {
	q1 := new(QueryError)
	subErr := fmt.Errorf("a sub error occurred: %w", q1)
	var q2 *QueryError
	fmt.Printf("%#v\n", &q2)
	if errors.As(subErr, &q2) {
		fmt.Println("subErr unwraps to q2")
	} else {
		t.Fatal("errors.As comparison failure")
	}
}

The blog post doesn't really mention this weirdness at all though.

I presume some folks like me are going to out of instinct remove either the * or the & in order to get one layer of nesting and then be confused when that's not correct. It might be good to add a note that, yes, this is the correct thing to do.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions