Comment by TheDong
5 months ago
netip is one of the newer additions to the stdlib (added in ~2022), and follows the venerable stringly typed error idiom.
I always interpreted the preference for stringly typed errors as a way to keep the Go language simpler. Good error handling is complicated and hard to read, and one of Go's values is that programs should be easy to read. As such, if you want good error handling, you should use a different language, like Java or Haskell or C++. This also helps keep people who might demand complicated things like generics away from the language, further keeping it simple.
My understanding was that many of the go idioms are there to scare off programming language theorists, who have a tendency to unnecessarily complicate everything with type theory, and error handling also seems to mostly be in that vein.
> and follows the venerable stringly typed error idiom.
Not exactly. It assumes that all error conditions within the functions provided by netip are of the same nature as it pertains to a single unit of work. In other words, there is only one type (not referring to the language's type system). Error type reuse where different failure points produce the same type of error does not violate current idioms. I cannot immediately think of any reason for why their assumption is wrong, so unless you have other ideas?
That is not the same situation as the deferred close wrapper, though. It is assuming that closing multiple file handles is the same operation, but clearly that's not true. If you were, say, writing a copy function the error handling of the read handle failure is unlikely to be the same as the handling of the write handle failure. The former doesn't tell you much, the latter is quite actionable. The failure points are distinct, and thus of different types (again, not referring to the type system).
The author's answer was basically that he is the only caller so if that problem arises in his code he'll simply modify the function to return idiomatic types. Which is fair for the lone wolf developer. When working alone anything goes! But it is not good API design generally speaking. It certainly wouldn't fly in something like the standard library or anywhere you have other developers.
> Error type reuse where different failure points produce the same type of error does not violate current idioms. I cannot immediately think of any reason for why their assumption is wrong, so unless you have other ideas?
I have a program that takes user input and parses it, and then displays an error. My program is for a language other than english so having it display a pop up with the message "invalid ip:port, square brackets can only be used with ipv6 addresses" in english is bad. Therefore I want to switch on the error message to display translated errors, but of course Go does not think that parsing errors are something that is important.
If parsing user input isn't a place to expose clear non-stringly-typed-errors, I don't know what is.
Note, it also gives bad errors in that some of them include details and the user input, and some don't, so displaying them to users will stutter or require parsing.
For example:
So in one case it has included the original user string, to make it clear what failed, and in another case it doesn't, so I'll have to always add in the context of the input (i.e. `fmt.Errorf("error parsing %q: %w", input, err)`) anyway in order to know what failed, but it'll stutter in every case where they do include the input.
I know the answer to all my issues is the usual go thing of "a little copying is better than depending on the go stdlib" of course. At least for netip, forking it is fine, having to maintain a fork of the go net/http stack just to get halfway decent errors is a real pain.
I'm not sure the desire to perform a transformation on a value implies that there are multiple types. You speak to a real problem, of course, but perhaps at the wrong layer of abstraction. It seems the deeper seeded issue is that Go strings assume one language, which is not true. I wonder what native internationalization support might look like?
2 replies →