Skip to content

proposal: errors: Fix errors.As to support more ergonomic usage with matching typed Errors #73461

Closed as duplicate of#51945
@wrouesnel

Description

@wrouesnel

Proposal Details

The current errors.As usage is non-sensical. In so much as we have to use two different functions already, the fact the following code will compile and fail despite looking right is madness:

package main

import (
	"errors"
	"fmt"
)

type ErrNew struct {
}

func (e ErrNew) Error() string {
	return "I'm an error"
}

func fn() error {
	return &ErrNew{}
}

func main() {
	if err := fn(); errors.As(err, &ErrNew{}) {
		fmt.Println("Got the error")
	} else {
		fmt.Println("Missed it")
	}
}

The correct code is of course this:

package main

import (
	"errors"
	"fmt"
)

type ErrNew struct {
}

func (e ErrNew) Error() string {
	return "I'm an error"
}

func fn() error {
	return &ErrNew{}
}

func main() {
	x := &ErrNew{}
	if err := fn(); errors.As(err, &x) {
		fmt.Println("Got the error")
	} else {
		fmt.Println("Missed it")
	}
}

But...why? errors is already using reflection to identify types here, and when we evaluate the first from we correctly deduce that err is *ErrNew - the problem is we convert targetType into ErrNew and then check for assignability....which obviously doesn't work because a pointer can't be assigned to a concrete struct which is the type we're comparing to now.

Basically why is As setup such that this very obvious way of using it doesn't work:

err := &ErrorNew{}
errors.As(err, &ErrNew{})

EDIT: I acknowledge there might be very good reasons this was done this way, but from an ergonomics perspective it's a disaster that Go will happily compile this and it will not work at all how you would expect - plus it's a lot of noise for those wanting to use typed errors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    LanguageProposalIssues describing a requested change to the Go language specification.Proposal

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions