3 ms·
Pointer to struct is not equivalent to an interface. You're not supposed to return your custom error-like struct pointers from functions - you're supposed to re
by bheadmaster 3y ago
Pointer to struct is not equivalent to an interface. You're not supposed to return your custom error-like struct pointers from functions - you're supposed to return an "error" interface. Just change the "QueryDatabase" to return "(string, error)" and your whole problem will disappear: https://go.dev/play/p/fb0e_4loDBf https://go.dev/play/p/fb0e_4loDBf
This is a common mistake when coming from exception-based-error-handling languages where exceptions are differentiated by type. In Go, if you want a more granular distinction between different kinds of errors, you don't use types, you use values: https://go.dev/play/p/ddzhAqRgK_1 https://go.dev/play/p/ddzhAqRgK_1
If you insist on using the typesystem for granular error checking, then you can define an "Is(target error) bool" method on your custom type to differentiate in the same way: https://go.dev/play/p/gZmYgOq6wSo https://go.dev/play/p/gZmYgOq6wSo
- the_gipsy 3y ago> You're not supposed to return your custom error-like struct pointers from functions - you're supposed to return an "error" interface Per https://github.com/golang/go/wiki/CodeReviewComments#interfaces https://github.com/golang/go/wiki/CodeReviewComments#interfa...: Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values. The implementing package should return concrete (usually pointer or struct) types There clearly is this one exception ONLY for the `error` interface. This advice plus the weird runtime check conventions like `Is` / `As` are nowhere to be seen for other interfaces in the ecosystem. Go makes a lot of effort so that errors are special. There is an exceptional tuple-type that exists solely for returning errors, and the error-return-interface convention breaks interface-return conventions. If they implemented sum-types, then we would have the typical `Result<T, Error>`, and then go programs would have much more invariants and be much more composable. But presumably compilation- and/or run-time would be worse. Another alternative would have been adding syntax sugar like rust's `?` for `if err != nil { return ..., err }`, and `match err { case CustomError: ... case error: ... case nil ... }`. And some helpers for composing/piping functions.
- rollcat 3y agoThere would be two major problems with sum types (especially for results) in Go 1.x: - There are genuine use cases where returning both a value and an error makes complete sense. My favourite example is doing I/O: some bytes were copied, but there was a problem with the rest. - It has significant overlap in scope & functionality with interface types. You could have "type Color enum { Named(string); RGB(int, int, int) }", or you could have "type Color interface { RGB() (int, int, int) }; type NamedColor string;" etc and it's not very clear which style you'd be supposed to use, and in what case. The first problem could be somewhat alleviated by having very special result types that can have both a return value and an error, but these would have to be different from regular "variant" results, so you'd end up either with two ways to do a very similar thing, or yet another layer of abstraction. The second problem is fundamental to the design of the language, and I would absolutely *hate* to see Go go through the same unholy mess as Python: "old-style" vs "new-style" classes, dataclasses (with third-party "attrs" as a stepping stone), protocols/generic containers, "match"/destructuring, all of these were clumsily grafted on and code that mixes all of these styles can be found all over the place. You do need to make ADTs and pattern matching a first-class citizen in 1.0, otherwise the place you end up in is not pretty at all. Go? Yeah, we have a lot of SortIntegers([]int) and SortStrings([]string) and SortByName([]Person) in older code, but that's about its biggest sin. As of 1.21, slices.Sort & slices.SortFunc are in std and fixing this older code is pretty much a mechanical task. It's not perfect, but at least it's not worse by trying too hard to be perfect.
- the_gipsy 3y ago> My favourite example is doing I/O: some bytes were copied, but there was a problem with the rest. How do you reconcile that with the general rule or convention that `if err != nil` the value is unsafe to use? Apart from this, I don't think sum-types should be added this late either. I should have written "if they had implemented". "old vs new style" does more damage than good. Today, it is what it is. What I do think is feasible is adding some more syntax sugar around errors.
- bheadmaster 3y ago