4 ms·
> This makes a zero value union very similar to a nil interface, which will also fail all type assertions. Yet is still directly comparable with 'i == nil' whi
by akira2501 2y ago
> This makes a zero value union very similar to a nil interface, which will also fail all type assertions.
Yet is still directly comparable with 'i == nil' which yields true. Two different interface pointers of the same type that are both 'nil' can also be compared this way. Plus interfaces can be manipulated under reflection.
> At this point my feeling is that Go might as well stick with interfaces and not attempt to provide union types.
The language, and most particularly the runtime, is not compatible with the idea. I'm not sure why it gets brought up other than language level FOMO.
- TheDong 2y ago> I'm not sure why it gets brought up other than language level FOMO. I think it gets brought up because people see places it would be helpful quite often. A lot of the Go code I've written has: switch x { case ....: case ....: default: panic(fmt.Sprintf("inexhaustive match, please update this switch statement for %v", x)) } Similarly, go supposedly has good error handling, but I constantly find myself writing: switch { case err == nil: case errors.Is(err, SomeErr): // handle SomeErr case errors.Is(err, OtherErr): // handle OtherErr case strings.Contains(err.Error(), "tls: unknown certificate authority")): // handle unexported go stdlib error, XXX fix after https://github.com/golang/go/issues/35234 default: panic(fmt.Sprintf("unhandled error type: %v: %T", err, err)) } Like, for being a statically typed language, Go's error handling is really bad, and sum types is the thing that would let me internally at least make error handling feel good. I could have my own functions return up a non `error`-interface type, not implement the `error` interface intentionally to avoid the nil-typed-interface problem 'err' is otherwise prone to, and then I could actually know when I compiled my codebase that my error handling is good, and know what needs to be updated after adding new error paths.
- XorNot 2y agoI mean...I'll say this, for all the great things spoken about it I also found myself wildly disappointed with Rust's error handling when I tried to use it (and then a pile of blog posts going "oh yeah, it does kind of suck..."). What I am yet to find in any programming language is a reliable way to put my cursor somewhere in the code base, and know exactly all the possible errors which can happen, where they could come from, and whether I've handled them (or might be interested in handling them). Fault-injection is also consistently a sore point - i.e. in Go if you're doing an os.Open(somefile) call - it'd be really nice if writing code which tests the failure path was just easier - i.e. most of the time I'm saying "this Open on this line, just return an error for this test case so I can make sure it does what I want" - without bogging myself down in dependency injection or call monitoring (i.e. realistically I just want to say "os.Open in file somefile.go, line 143 - for this test please just return err"). Yes something like this can be done, but can we really not make this easier? Write tools which make this easier?
- rto_victim 2y agoAgreed. Sum types require too much boilerplate for error handling as they require wrapping and unwrapping which leads to people creating crate-level error enums that have every possible injection. Ideally we'd have unions which gets rid of the bike shedding that comes with sums [1]. [1]: https://gvolpe.com/blog/error-handling-scala3/ https://gvolpe.com/blog/error-handling-scala3/
- andyferris 2y agoRoc's polymorphic tagged unions seem to be the sweet spot of not requiring specially-crafted enums or multiple levels of unwrapping, yet having lots of statically-checked guarantees. (Zig is similar but doesn't support different types of payloads on the different error values).
- tubthumper8 2y agoUntagged unions lack the ability to model "the success value is a string and the error is a string", right?
- rto_victim 2y agoThat's correct. In your case you can either model it with a sum type or wrap each variant in its own type and take the union of them. Example: enum Result { Success(String), Error(String), } struct Success(String); struct Error(String); type Result = Success | Error;
- fao_ 2y ago> What I am yet to find in any programming language is a reliable way to put my cursor somewhere in the code base, and know exactly all the possible errors which can happen, where they could come from, and whether I've handled them (or might be interested in handling them). Zig's error types and error unions seem like a decent approach to achieve this.
- metaltyphoon 2y ago
- tucnak 2y agoI'm not bothered to `switch` errors, however I really wish I could also match against both static errors (ErrSomethings) and error _types_ in a single `switch`, because now whenever I want to properly handle most errors, I need at least two `switch` statements. There's also the issue of type-matching deeply-wrapped types which is non-trivial (requiring a for loop.) If only they could solve this syntactically...
- shepherdjerred 2y agoGo is great for certain kinds of programmers. For other programmers, it's missing critical features. For me, it is very important to be able to model my domain in the type system. You can't do that very well (compared to other languages) with Go's type system. I would choose Go over any dynamically typed language. I wouldn't pick it over most statically typed languages.
- cmrdporcupine 2y agoExactly this. I'd pick it over Python. I might even pick it over Java, which I think is kinda... barely statically typed. But thinking in strong types and making the type system my friend has saved my ass and improved my productivity so much over the years... I find programming in Go is like working with one arm tied behind my back. The emphasis on simplicity is a laudable goal. The problem is they picked the wrong definition of "simple"
- masklinn 2y ago> I might even pick it over Java, which I think is kinda... barely statically typed. Go’s type system is really not much better than Java, if it’s not worse.