admin管理员组

文章数量:1025295

I want to be able to get the individual errors within a wrapped error, either in a slice or to get the error that is removed when calling errors.Unwrap()

I've tried using the Unwrap() function available in the errors package but it doesn't quite achieve what I want, since it returns the rest of the wrapped error without the first error that is removed

I'm aware of the Cause() function available in the pkg/errors package on GitHub but as far as I can tell this is not maintained anymore since the repo is archived and would require me to use their errors.Wrap() function everywhere instead of fmt.Errorf().

I want to be able to get the individual errors within a wrapped error, either in a slice or to get the error that is removed when calling errors.Unwrap()

I've tried using the Unwrap() function available in the errors package but it doesn't quite achieve what I want, since it returns the rest of the wrapped error without the first error that is removed

I'm aware of the Cause() function available in the pkg/errors package on GitHub but as far as I can tell this is not maintained anymore since the repo is archived and would require me to use their errors.Wrap() function everywhere instead of fmt.Errorf().

Share Improve this question edited Nov 18, 2024 at 13:09 DarkBee 15.5k8 gold badges72 silver badges118 bronze badges asked Nov 18, 2024 at 13:09 boncularsbonculars 644 bronze badges 5
  • Not sure, if you want to unwrap all the errors or the first error that caused it. Could you clarify with an example – Inian Commented Nov 18, 2024 at 14:20
  • An example would be something like having an error of wrapped error again: wrapped error: error and I would want to get each piece of that wrapped error again, wrapped error and error. The errors.Unwrap() function only allows for getting the wrapped error minus the most recent error, so taking that example calling errors.Unwrap() on that error would return wrapped error: error and I want to be able to either retrieve the wrapped error again that has been omitted or get the pieces of the returned error somehow, doesn't have to be using Unwrap() to do it. – bonculars Commented Nov 18, 2024 at 14:36
  • There is no error of string just wrapped error again, imagine you were wrapping it, you would have the following baseErr := errors.New("base error") wrappedOnce := fmt.Errorf("wrapped error: %w", baseErr) wrappedTwice := fmt.Errorf("wrapped error again: %w", wrappedOnce). As you can see wrappedTwice will have an an error specifier that wraps the error from layer below. – Inian Commented Nov 18, 2024 at 15:04
  • Sounds like your initial premise of how errors in Go programs are structured is a bit wrong. @bonculars is correct in that in a typical program which uses nothing but core Go functions (including those of the standard package errors), there may be either a single error or a logical chain of errors, where an error at each individual node of such chain is able to get a single "causing" error—all the way down to the "root" one. There's no slice of errors or something like this. – kostix Commented Nov 18, 2024 at 16:13
  • 1 I would stress that a chain of errors is a logical construct as calling Unwrap() on an error value is free to "cook" and return an error value right on the spot; nothing oblidges it to fetch some stored value—even though it's what is done most of the time. – kostix Commented Nov 18, 2024 at 16:17
Add a comment  | 

1 Answer 1

Reset to default 0

I'm afraid no, since there are no independent components.

Let's examine a simple example:

package main

import (
    "errors"
    "fmt"
)

func main() {
    a := errors.New("a")

    b := fmt.Errorf("b: %w", a)

    fmt.Println(b.Error())
}

which prints “b: a”. Now, looking at the source of fmt.Errorf:

        w := &wrapError{msg: s}

we see we get the unexported structure fmt.wrapError:

type wrapError struct {
    msg string
    err error
}

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

So, “b: a” is the msg part of this error and not separable in any way. You can have other wrapping mechanisms, but generally the wrapping error contains the wrapped errors.

What would be your use case? Maybe there is another way to achieve the functionality you desire?

I want to be able to get the individual errors within a wrapped error, either in a slice or to get the error that is removed when calling errors.Unwrap()

I've tried using the Unwrap() function available in the errors package but it doesn't quite achieve what I want, since it returns the rest of the wrapped error without the first error that is removed

I'm aware of the Cause() function available in the pkg/errors package on GitHub but as far as I can tell this is not maintained anymore since the repo is archived and would require me to use their errors.Wrap() function everywhere instead of fmt.Errorf().

I want to be able to get the individual errors within a wrapped error, either in a slice or to get the error that is removed when calling errors.Unwrap()

I've tried using the Unwrap() function available in the errors package but it doesn't quite achieve what I want, since it returns the rest of the wrapped error without the first error that is removed

I'm aware of the Cause() function available in the pkg/errors package on GitHub but as far as I can tell this is not maintained anymore since the repo is archived and would require me to use their errors.Wrap() function everywhere instead of fmt.Errorf().

Share Improve this question edited Nov 18, 2024 at 13:09 DarkBee 15.5k8 gold badges72 silver badges118 bronze badges asked Nov 18, 2024 at 13:09 boncularsbonculars 644 bronze badges 5
  • Not sure, if you want to unwrap all the errors or the first error that caused it. Could you clarify with an example – Inian Commented Nov 18, 2024 at 14:20
  • An example would be something like having an error of wrapped error again: wrapped error: error and I would want to get each piece of that wrapped error again, wrapped error and error. The errors.Unwrap() function only allows for getting the wrapped error minus the most recent error, so taking that example calling errors.Unwrap() on that error would return wrapped error: error and I want to be able to either retrieve the wrapped error again that has been omitted or get the pieces of the returned error somehow, doesn't have to be using Unwrap() to do it. – bonculars Commented Nov 18, 2024 at 14:36
  • There is no error of string just wrapped error again, imagine you were wrapping it, you would have the following baseErr := errors.New("base error") wrappedOnce := fmt.Errorf("wrapped error: %w", baseErr) wrappedTwice := fmt.Errorf("wrapped error again: %w", wrappedOnce). As you can see wrappedTwice will have an an error specifier that wraps the error from layer below. – Inian Commented Nov 18, 2024 at 15:04
  • Sounds like your initial premise of how errors in Go programs are structured is a bit wrong. @bonculars is correct in that in a typical program which uses nothing but core Go functions (including those of the standard package errors), there may be either a single error or a logical chain of errors, where an error at each individual node of such chain is able to get a single "causing" error—all the way down to the "root" one. There's no slice of errors or something like this. – kostix Commented Nov 18, 2024 at 16:13
  • 1 I would stress that a chain of errors is a logical construct as calling Unwrap() on an error value is free to "cook" and return an error value right on the spot; nothing oblidges it to fetch some stored value—even though it's what is done most of the time. – kostix Commented Nov 18, 2024 at 16:17
Add a comment  | 

1 Answer 1

Reset to default 0

I'm afraid no, since there are no independent components.

Let's examine a simple example:

package main

import (
    "errors"
    "fmt"
)

func main() {
    a := errors.New("a")

    b := fmt.Errorf("b: %w", a)

    fmt.Println(b.Error())
}

which prints “b: a”. Now, looking at the source of fmt.Errorf:

        w := &wrapError{msg: s}

we see we get the unexported structure fmt.wrapError:

type wrapError struct {
    msg string
    err error
}

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

So, “b: a” is the msg part of this error and not separable in any way. You can have other wrapping mechanisms, but generally the wrapping error contains the wrapped errors.

What would be your use case? Maybe there is another way to achieve the functionality you desire?

本文标签: goIs there a way to split a wrapped error into its individual componentsStack Overflow