Also, if error wrapping hurts you so much (I don't use it), just implement a project-specific error that works how you want. This could be something that is JSON serializable, that captures a line number at each return site, etc. It will take like 10 minutes to get your project's errors working exactly how you want.
My projects usually do -
log.SetFlags(log.LstdFlags | log.Lshortfile)
// ...
if err != nil {
log.Println(err)
return errors.New("Error doing the thing.")
}
That essentially logs a stack trace with line numbers up the whole error chain, each return adding the outer context. I only ever use errors.Is for os.ErrNotExist.
I know about slices module. But GP is not happy about generics apparently.
I think your error solution is good. But still it's a poor imitation of Exceptions wherein you have to capture the stack trace manually, possibly incuring a perf hit (haven't measured), and write handling code in every layer. Made worse by the fact that people return desperate errors for even precondition violations which should be panics.
Also, if error wrapping hurts you so much (I don't use it), just implement a project-specific error that works how you want. This could be something that is JSON serializable, that captures a line number at each return site, etc. It will take like 10 minutes to get your project's errors working exactly how you want.
My projects usually do -
That essentially logs a stack trace with line numbers up the whole error chain, each return adding the outer context. I only ever use errors.Is for os.ErrNotExist.