-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Version of Append that does not flatten #5
Comments
@bits01 Yo check it: Code with a solution to an example of your problem: package main
import (
"fmt"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
)
func subTask1(errorChannel chan error) {
var err error
err = multierror.Append(err, fmt.Errorf("error foo"))
err = multierror.Append(err, fmt.Errorf("error bar"))
errorChannel <- err
}
func subTask2(errorChannel chan error) {
var err error
err = multierror.Append(err, fmt.Errorf("error foo"))
errorChannel <- err
}
func subTask3(errorChannel chan error) {
var err error
err = multierror.Append(err, fmt.Errorf("error foo"))
err = multierror.Append(err, fmt.Errorf("error bar"))
errorChannel <- err
}
func main() {
errorChannel1 := make(chan error, 1)
errorChannel2 := make(chan error, 1)
errorChannel3 := make(chan error, 1)
go subTask1(errorChannel1)
go subTask2(errorChannel2)
go subTask3(errorChannel3)
err1 := <- errorChannel1
err2 := <- errorChannel2
err3 := <- errorChannel3
var err error
// Prefix each error in the multierror with a nested tab+asterisk
err1 = multierror.Prefix(err1, "\t*")
err2 = multierror.Prefix(err2, "\t*")
err3 = multierror.Prefix(err3, "\t*")
// Wrap each multierror to stop multierror flattening
err1 = errwrap.Wrap(err1, nil)
err2 = errwrap.Wrap(err1, nil)
err3 = errwrap.Wrap(err3, nil)
err = multierror.Append(err, err1, err2, err3)
fmt.Println(err)
} Output:
|
@mitchellh and the rest of the Hashicorp folks, how do you feel about adding something like this into func DontFlatten(err error) {
if _, ok := err.(*Error); !ok {
return err
}
err = Prefix(err, "\t*")
return errwrap.Wrap(err, nil)
} Usage would look like this mErrs := new(multierror.Error)
// ... got an `err` that may be a `multierror.Error` that we don't want to flatten:
err = multierror.Append(mErrs, multierror.DontFlatten(err)) If the answer is yes, I'll happily do a pull request and sign your CLA or whatever. In the meantime I license it under the Zero-Clause BSD license (SPDX short identifier: 0BSD) and to my knowledge it doesn't (and in most jurisdictions can't, because it's so obvious) fall under any patents, so I'm pretty sure legally you're allowed to use it as if it was public domain anyway (but this does not consistute legal advice, I'm not a lawyer, etc). |
Some potential downsides I can see to the above proposed
Despite all this, it's probably still good enough for the most common and the most simple usecases as-is, but that's not for me to decide so I wanted to make sure I drew attention to all these. |
Update re: above CLA comment: I've now signed your CLA. |
Question: are people like me just missing some wisdom in favor of not nesting errors? It seems that both Hashicorp's multierror and Uber's multierr exclusively expose a way that flattens the errors. Past experience suggests that when I find myself limited by something like this, it could be just because I'm wrong in wanting to do what I'm trying to do. It seems that my own current use-cases could be equally solved by:
Okay, I think I have some clarity now. My desire for this feature was naive. That doesn't mean it's wrong - there may be a right reason for wanting it that I just haven't seen yet. But it seem that every place I found myself wanting it can and should be solved another way. |
(and I'm not using |
I realize that
Append()
was fixed at some point to flatten, but I believe it's valuable to have a version of it that does not flatten MultiErrors. Use case: execute a bunch of tasks in parallel, wait for them to finish, collect the errors from the failed tasks and return them to the caller as a single MultiError. I would like to be able to preserve any MutliError generated by each task rather than ending up with a flat list of errors that lost their context, the demarcation points between tasks if you will.The text was updated successfully, but these errors were encountered: