No.
I kind of want to leave it there. But that will probably be looked on disfavorably.
I've seen at least a dozen attempts. It's not like it's hard to write it out. There's maybe a couple of variants but they're all just a handful of lines. The problem is, once you have an Option in hand, you end up trading:
val, err := whatever(...)
if err != nil {
// handle error
}
// use val
for val := whatever(...)
if err, isErr := val.Error(); isErr {
// handle error
}
realVal := val.Value()
// use realVal
What you win in nominal safety, you're definitely losing in convenience.There's also no win in trying to offer a monadic interface like
finalVal := whatever(...).OnVal(func (val Value) opt.Option[Result] {
// use val
})
because that's the minimal specification of an anonymous function in Go, so it's very inconvenient. Even if that was trimmed down, nested functions are still problematic in other ways. And you still have to unpack finalVal anyhow.Really the solution is, install golangci-lint, turn on errcheck [1], use a pre-commit hook to make it a commit failure if golangci-lint fires, and that pretty much covers the problem in practice.
One of the problems with Option/Result/etc. advocacy... not the pattern itself, the advocacy... is that it is generally are presented, implicitly or explicitly, as if the alternative is C, with its errno and the need to not just check an error value, but remember to go actively seeking out errors constantly, making it easy to forget. But by modern standards, that's completely pathological.
If we rate error handling techniques on a scale from 1 to 10 (best), C here is a 1, and standard Option is maybe an 8 or a 9. The way Go does it is maybe a 6; it is completely true that you can neglect to handle an error (see errcheck comment in previous paragraph), but it is in your face that an error is possible, and that's really most of the problem. Putting Option/Result/etc. is not always a "go from 1 to 9" result. "Go from 6 to 8" is a much less impressive proposition, and the other inconveniences that come with it in Go tend to overwhelm the gain. I use errcheck all the time, and even in the Before Times when I was writing it all by hand it really didn't fire all that often. Especially if I exclude test code. In an AI era this hardly rates at all. AI never neglects the error.
Whether it does the right thing with it, now... that's another story entirely.
Read those error handling clauses if you're writing Go with AI. I really don't like what I've seen AIs do with them by default. What I've seen out of AI has been very thoughtless. Nominally correct in some weak sense, but thoughtless.
[1]: https://golangci-lint.run/docs/linters/configuration/#errche...
I think my opinion will be even more maligned: I like Java-style checked exceptions. It forces awareness of the error and a clean way to propagate it.