Closed
Description
I've hit a surprising number of cases recently where I wished that multierr.Append
would tell me if the append happened or not. It's not so much for dubious micro perf reasons (CPUs being cheap, fast, and plentiful these days), but more on account of simplifying control flow:
- when I don't need to tell if it happened, I can use the inline form like
err = multierr.Append(err, somethingFaliable())
- but if I need to know if
somethingFaliable
failed or not in addition to collecting its error, then I have to break that apart, and do my own nil check - really the hardest part of this, as always, is choosing what to name
someErr
;-)
package main
type T struct{}
type Scanable interface {
Scan(...interface{}) bool
}
// harvestT loads T from some Scanable source. Since we really like T, we don't
// let mundane details like parsing errors get in our way; instead we continue
// on to harvest as much T as we can, collecting any errors that we encounter.
func harvestT(iter Scanable) ([]T, error) {
var (
mess string // each string from the db
datum T // each parsed item
data []T // all items parsed
retErr error // any collected errors
)
// with current multierr
for iter.Scan(&mess) {
if parseErr := tryToParse(s, &datum); parseErr != nil {
retErr = multierr.Append(retErr, parseErr)
continue
}
data = append(data, datum)
}
// however what if we could:
for iter.Scan(&mess) {
retErr, failed = multierr.Appended(retErr, parseErr)
if failed {
continue
}
data = append(data, datum)
}
// or even "better" in this case:
for iter.Scan(&mess) {
retErr, failed = multierr.Appended(retErr, parseErr)
if !failed {
data = append(data, datum)
}
}
// alternatively, if we used a *error:
for iter.Scan(&mess) {
if multierr.AppendInto(&retErr, parseErr) {
continue
}
data = append(data, datum)
}
// which of course could be simplified in our singleton case (you wouldn't
// want to do this if you had more than one faliable step in the loop
// body):
for iter.Scan(&mess) {
if !multierr.AppendInto(&retErr, parseErr) {
data = append(data, datum)
}
}
return data, retErr
}