-
Notifications
You must be signed in to change notification settings - Fork 1
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
Go: Improve error handling #112
Comments
Some other links that I wrote down somewhere: |
https://github.com/rotisserie/eris
|
The most promising alternative right now is indeed https://github.com/cockroachdb/errors .
|
https://github.com/Southclaws/fault
|
Writing our own error lib.
Some code I played around with. Note that there are a few open questions e.g. is a public type Tree interface {
Error() string
FriendlyError() string
Unwrap() []error
Location() string
}
func New(msg string) Tree {
return new(msg, "")
}
func new(msg, friendlyMsg string) Tree {
return defaultTree{
msg: msg,
friendlyMsg: friendlyMsg,
location: getLocation(4),
children: nil,
}
}
func NewFriendly(msg string, friendlyMsg string) Tree {
return new(new, friendlyMsg)
}
// Newf includes formatting specifiers.
func Newf(message string, va ...any) Tree {
return new(fmt.Sprintf(message, va...), "")
}
func Wrap(err error, msg string) Tree {
return wrapMulti([]error{err}, msg)
}
func WrapMulti(errs []error, msg string) Tree {
return wrapMulti(errs, msg)
}
func wrapMulti(errs []error, msg string) Tree {
allNil := true
for _, e := range errs {
if e != nil {
allNil = false
}
}
if len(errs) == 0 || allNil {
return nil
}
var children []Tree
for _, e := range errs {
if child, ok := e.(Tree); ok {
children = append(children, child)
} else {
children = append(children, externalError{err: e})
}
}
return defaultTree{
msg: msg,
location: getLocation(4),
children: children,
}
}
type defaultTree struct {
msg string
friendlyMsg string
location string
children []Tree
}
func (t defaultTree) Error() string {
switch len(t.children) {
case 0:
return t.msg
case 1:
return fmt.Sprintf("%v: %v", t.msg, t.children[0].Error())
default:
var cMsgs []string
for _, c := range t.children {
cMsgs = append(cMsgs, c.Error())
}
return fmt.Sprintf("%v: [%v]", t.msg, strings.Join(cMsgs, " | "))
}
}
func (t defaultTree) FriendlyError() string {
switch len(t.children) {
case 0:
return t.msg
case 1:
return fmt.Sprintf("%v %v", t.msg, t.children[0].Error())
default:
var cMsgs []string
for _, c := range t.children {
cMsgs = append(cMsgs, c.Error())
}
return fmt.Sprintf("%v (%v)", t.msg, strings.Join(cMsgs, " ; "))
}
}
func (t defaultTree) Unwrap() []error {
var errs []error
for _, c := range t.children {
errs = append(errs, c)
}
return errs
}
func (t defaultTree) Location() string {
return t.location
}
// externalError wraps errors not created by 'errtree'.
// It adds no information and acts as a transparent gateway.
type externalError struct {
err error
}
func (t externalError) Error() string {
return t.err.Error()
}
func (t externalError) FriendlyError() string {
return ""
}
func (t externalError) Unwrap() []error {
return []error{t.err}
}
func (t externalError) Location() string {
return ""
}
func getLocation(skip int) string {
pc := make([]uintptr, 1)
runtime.Callers(skip, pc)
cf := runtime.CallersFrames(pc)
f, _ := cf.Next()
return fmt.Sprintf("%s:%d", f.File, f.Line)
} |
cockroachdb/errors gives us stack traces and information for end users with WithHint(). The reason for the 'errors' wrapper package is so as not to spread a third party dependency all over the code and make it easier to replace should that ever become necessary. If the API of the internal 'errors' keeps growing and becoming closer and closer to cockroachdb/errors then at some point the internal package might be deleted. In schema.resolvers.go it was necessary to import the packages as 'errors2' because otherwise the automated code generation kept overriding it.
Right now I'm wrapping with fmt.Errorf("%w") and using go-multierror to convert multiple errors into one.
Dave Cheney says he no longer wraps. Why? What is the alternative? github.com/pkg/errors is archived. https://groups.google.com/g/golang-nuts/c/FjtjR87-1qM
https://dr-knz.net/cockroachdb-errors-everyday.html
https://github.com/cockroachdb/errors
cockroach package seems a little bloated. Many others don't seem to be tracking the stack trace al all?
https://www.southcla.ws/go-error-wrapping/
Looks nice: https://github.com/Southclaws/fault
Has stack, has user friendly messages, but seems a rather new project, is it worth adding as a dependency?
Ideally what I would like:
The text was updated successfully, but these errors were encountered: