I understand the problem you are trying to solve, and it's valid, I think. But this solutions "feels" bad and very un-Go-like. Usable zero values is a feature in Go. Whether you agree with that or not, it's a selling feature of the language and clearly something that was/is important to the Go Authors - as is explicit vs implicit logic. So having a zero value that implicitly means "don't use this" a a feature that is built into the language seems like it could lead to confusion or at least a very muddled message about the nature and purpose of Go.
I think maybe where your opinion diverges from the "hive mind" here is that you want the compiler to enforce this notion. You can already achieve your basic objective with your "Additional Bool" example, and the confusion you complain about there can be easily mitigated with a better named variable "IsSet" rather than "IsZero" like Brian Candler suggested. But you still wouldn't have compile-time enforcement. And that I think is where Go is going to disappoint you. Go is a strongly typed language, at least on the scale of QBasic to Pascal, but the compiler does allow you to do a lot of things that you shouldn't, in the interest of letting you do things that might be a little crazy but that still work. It seems to me that Go likes to leave "should" rules to the linter rather than the compiler, so maybe you could use a custom linter to achieve what you're looking for? It's not a perfect solution, but it feels like it gets you 90% there. On Monday, March 18, 2024 at 4:42:32 AM UTC-4 Brian Candler wrote: > I like Go because it's relatively simple and low-level, like C, except > with things like garbage collection and channels integrated. If Go were to > have "| nil" types then the internal representation of such variables would > have to be something like this: > > type Maybe[T any] struct { > Value T > IsSet bool > } > > In which case, why not just use that form explicitly? The code you write > is then clear and obvious. Taking one of your examples: > > func foo3(x Maybe[int]) { > if x.IsSet { > fmt.Println("x squared is", x.Value*x.Value) > > } else { > fmt.Println("No value for x") > } > } > > // https://go.dev/play/p/ci10fhU1zqL > > I also think that you need to find multiple compelling use cases (of which > that example is not one), before fundamentally adding complexity to the > language. Remember that "nil" is already overloaded in Go, so adding > another (similar but different) meaning increases complexity for the reader. > > Full union types are a different thing again, and I can see the attraction > of those - except at that point, the language is no longer Go. Having > "int32 | int64" as a union type, but also as a generic type constraint, > would also be somewhat mind-boggling. How would you write a type constraint > that allows a union type? > > On Monday 18 March 2024 at 07:01:25 UTC Jan Mercl wrote: > >> On Mon, Mar 18, 2024 at 4:41 AM Daniel Lepage <dple...@gmail.com> wrote: >> >> > This change would be entirely backward-compatible ... >> >> Let's consider, for example, the type uint8, aka byte. A variable of >> type byte is specified* to occupy 8 bits of memory and has 256 >> possible values. To represent all those values and the new possibility >> of the value being nil, we need 257 distinct values. But that does not >> fit 8 in bits anymore. However, changing the size and/or the bit >> representation of such a variable is observable, making it not >> backwards-compatible. >> >> ---- >> *: From https://go.dev/ref/spec#Numeric_types: >> >> """" >> The value of an n-bit integer is n bits wide and represented using >> two's complement arithmetic. >> """" >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e45d298f-154d-49c1-9316-73df4f250543n%40googlegroups.com.