This seems like a real sticking point for a lot of people. Personally, I don't seem to think about code volume in units of "lines" but rather in units of "complexity" and "locality". I would like to see Result and Optional types, but in practice everyone understands that (nil, err) is the same as Result::Err and that (*T, nil) is the same as Result::Ok. Of course, you miss out on monadic properties, but after extensively using the language, that's a
feature 99% of the time. I would say give it a shot; I was skeptical at first, but this is surprisingly not an issue IMO.
The real issues (IMO) with Go error handling are the clunky `errors.Is()` and `errors.As()` functions for catching specific error values and types respectively as well as annotating errors to get the requisite context (this may already have a solution which just hasn't yet become idiomatic across the ecosystem). In the meanwhile, I just wrap errors with extra context which isn't super satisfying but largely does the trick, e.g., `return fmt.Errorf("writing to database: %w", err)`. Rust seems to have similar problems with respect to different patterns and libraries for error handling, despite having a standard Result type.