This is equivalent to the problem of throwing new Exception("some message") or new RuntimeException("some message") in Java, to be fair. But this is more rarely done there in my experience, especially because people are more used to defining new exception types since the stdlib has many examples of that, unlike Go (which all returns `error` for all error types).
The way code usually looks like is this:
func foo(arg int) error {
if arg < 0 {
return fmt.Errorf("expected >0, got %d", arg)
}
if arg > 8 {
return fmt.Errorf("expected >8, got %d", arg)
}
//do stuff
}
or func foo(arg int) error {
if arg < 0 {
return errors.New(fmt.Sprintf("expected >0, got %d", arg))
}
if arg > 8 {
return errors.New(fmt.Sprintf("expected >8, got %d", arg))
}
//do stuff
}
In either of these cases, a caller of foo() can at best parse err.String() to see why foo() complained. But there is no way that errors.As or errors.Is help with the majority of errors returned by Go programs.You still need a stable error to compare against in errors.Is. fmt.Errorf is not going to provide that if the message is dynamic - which is almost always.
So, in practice, neither errors.Is nor errors.As are terribly useful, and %w just gives you a false sense of usefulness.