Concrete type error snippet in Golang

PHPz
Release: 2024-02-05 22:12:12
forward
965 people have browsed it

Golang 中具体类型的错误片段

Question content

I am trying out error wrapping in go and have a function that returns a wrapped custom error type. What I want to do is iterate over a list of expected errors and test whether the function's output contains these expected errors.

I found that putting the custom error into []error means that the type of the custom error will be *fmt.wraperror, which means errors.as( ) almost always returns true.

As an example, consider the following code:

package main

import (
    "errors"
    "fmt"
)

type anothererror struct {
}

func (e *anothererror) error() string {
    return "another error"
}

type missingattrerror struct {
    missingattr string
}

func (e *missingattrerror) error() string {
    return fmt.sprintf("missing attribute: %s", e.missingattr)
}

func dosomething() error {
    e := &missingattrerror{missingattr: "key"}
    return fmt.errorf("dosomething(): %w", e)
}

func main() {
    err := dosomething()
    expectederrone := &missingattrerror{}
    expectederrtwo := &anothererror{}
    expectederrs := []error{expectederrone, expectederrtwo}

    fmt.printf("is err '%v' type '%t'?: %t\n", err, expectederrone, errors.as(err, &expectederrone))
    fmt.printf("is err '%v' type '%t'?: %t\n", err, expectederrtwo, errors.as(err, &expectederrtwo))

    for i := range expectederrs {
        fmt.printf("is err '%v' type '%t'?: %t\n", err, expectederrs[i], errors.as(err, &expectederrs[i]))

    }
}
Copy after login

The output is

is err 'dosomething(): missing attribute: key' type '*main.missingattrerror'?: true
is err 'dosomething(): missing attribute: key' type '*main.anothererror'?: false
is err 'dosomething(): missing attribute: key' type '*fmt.wraperror'?: true
is err 'dosomething(): missing attribute: key' type '*fmt.wraperror'?: true
Copy after login

Ideally I would like the output to be

Is err 'DoSomething(): missing attribute: Key' type '*main.MissingAttrError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*main.AnotherError'?: false
Is err 'DoSomething(): missing attribute: Key' type '*main.MissingAttrError'?: true
Is err 'DoSomething(): missing attribute: Key' type '*main.AnotherError'?: false
Copy after login

The reason for the error is that I want to be able to define a list of expected errors for each test case entry. Suppose I know that providing certain inputs to a function will cause it to follow a path and return errors containing a specific error.

How do I convert the *fmt.wraperror type from the []error slice back to the original type so that I can use it with error.as?

I know I can use to cast it to a specific type. (anothererror), but in order to make it work when iterating over slices, I have to do this for every possible error the function might return, no? )


Correct answer


You can cheat using the following method errors.as:

func main() {
    err := DoSomething()
    m := &MissingAttrError{}
    a := &AnotherError{}
    expected := []any{&m, &a}

    for i := range expected {
        fmt.Printf("Is err '%v' type '%T'?: %t\n", err, expected[i], errors.As(err, expected[i]))
    }
}
Copy after login

The type printed is not what you expect, but errors.as works as it should.

The reason your example doesn't work is that what you're passing to errors.as is *error. Therefore, the wrapped error value (i.e. err) is assigned directly to the target value. In my example, the value passed to errors.as is **anothererror, and err is not assignable to *anothererror.

The above is the detailed content of Concrete type error snippet in Golang. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template