3 ms·
First, I consider warts of the language to be things that are side effects of the way the language is designed. This means that I would have loved for Go to hav
by nemothekid 6y ago
First, I consider warts of the language to be things that are side effects of the way the language is designed. This means that I would have loved for Go to have non-nullable types, Pike didn't bless Go with that feature. Same for generics and the other popular criticisms. That said the other 2 are
1. Error handling. Not only is `if err == nil` (or my preferred `if _, err := foo(); err == nil`) a lot of noise, errors are completely opaque and might as well be strings.
2. Dependency management. It was a mess for a long time, go modules fixed a lot of issues in it's own way but still has problems (e.g. the "v2" workaround). My theory is they expected everyone, in some way, to "self-host" their modules (like how Java would have com.google.foo.bar, eventually everyone else would have "http://go.company/package http://go.company/package", but GitHub became central repository of software for everyone and linking directly to packages was no longer sound).
- tgv 6y ago#1 has improved a bit lately, but I did get some mileage out of making my own type which carries an optional HTTP status, a severity level, the core error and an optional payload; and it implements Error(). It allows for easy logging, and can be used to return to the http client with a variety of messages.
- tptacek 6y agoErrors in Go have been queryable chains since 1.13; it's pretty seamless with `%w`. Rust has the `?` shorthand, which is very convenient, but also the annoyance of type matching errors, particularly across different libraries, to the point where third-party error handling libraries like `anyhow` are pretty important. Leaving nil itself out of the picture (obviously, I'd rather Go had Option types), I don't know that either language has a definitive edge here. Errors in modern Go are definitely not just strings. Before wrapped errors in Go, this would have been an easier case to make against the language.
- tsimionescu 6y agoMost errors in Go are still just strings, potentially with some comparison possible witht sentinel values like in the "io" package. As and Is give some nice tools, but its still up to documentation to decide which one to use, and different packages have different conventions for returning error types vs error values.
- saturn_vk 6y agoMost errors are probably strings since there probably is nothing you can customize as a handling for such particular error types. Now, if one could do something with a certain error class, then such error are usually not strings.
- iudqnolq 6y agoAnyhow's tagline is literally "a better Box<dyn Error>", which gets you nearly the same result modulo some pretty printing.
- tptacek 6y agoYes, Anyhow is almost as easy to use as Go's current error handling.
- iudqnolq 6y agoYou're significantly more experienced than me, so I'll defer to you here. What you're saying doesn't make sense to me though.
- tptacek 6y agoYou're probably more experienced than I am with Rust!
- iudqnolq 6y agoI might be misunderstanding go, but I think the big difference is you use anyhow to get looses error handling at the edges of binaries. It'd be weird to see in a published library, and unusual to see deep in an internal library that supports a binary. Whereas in go you do that sort of error handling everywhere.
- tptacek 6y agoI think %w makes sense in libraries, too. They're structured errors that behave like strings. It's a neat trick.
- jrockway 6y agoHow are errors opaque? If you want a FooError: foo := &FooError{} if errors.As(err, &foo) { fmt.Println("foo error!") }