TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Union types ('enum types') would be complicated in Go

28 pointsby misonic6 months ago

10 comments

pjmlp5 months ago
No it wouldn&#x27;t, as there are garbage collected systems programming languages with them, already 40 years ago, but as usual in Go, we ignore computing history.<p>Additionally, just having actual enumerations, Pascal &#x2F; Algo style, not ML style, would already be an improvement over the iota&#x2F;const hack.
评论 #42347914 未加载
foldr6 months ago
I think this is mistaken. Go already has a way to represent &#x27;open&#x27; union types (interfaces), so all of these runtime problems have already been solved. What&#x27;s missing is just the type system support to do exhaustive matching on the members of the union. With the addition of generics, &#x27;all&#x27; that would be necessary is to make the following a legal variable definition:<p><pre><code> var foo interface { struct { A int } | struct { B string } } </code></pre> It currently fails with the following error:<p>&quot;cannot use type interface{struct{A int} | struct{B string}} outside a type constraint: interface contains type constraints&quot;
评论 #42319851 未加载
评论 #42347043 未加载
评论 #42348390 未加载
brundolf5 months ago
Forget Result, just allow the type system to express non-nullable object references. Use the same layout, just let the compiler know when something is guaranteed to exist and force null-checking when it isn&#x27;t<p>This doesn&#x27;t cover everything people might want to do with unions, but it covers the billion-dollar mistake and doesn&#x27;t run against the grain of the entire language (as far as I know)
评论 #42348345 未加载
评论 #42350626 未加载
melodyogonna5 months ago
The important detail that has bogged down almost every union type discussion is &quot;zero values&quot;. What would be the zero value of a union type? If you&#x27;ve written Go you know the entire language is built around zero values, disabling it for some types is not an option.
评论 #42348329 未加载
评论 #42347967 未加载
eru5 months ago
&gt; At one level we easily do something that looks like a Result type in Go, especially now that we have generics. You make a generic struct that has private fields for an error, a value of type T, and a flag that says which is valid, and then give it some methods to set and get values and ask it which it currently contains. If you ask for a sort of value that&#x27;s not valid, it panics. However, this struct necessarily has space for three fields, where the Rust enums (and generally union types) act more like C unions, only needing space for the largest type possible in them and sometimes a marker of what type is in the union right now.<p>That seems better than not having algebraic data types at all.
lordofgibbons5 months ago
This is sorely needed to simplify error handling and getting rid of nil pointers panics. Would love to see a linter written for Go after something like this is created to ensure absolutely no naked pointer is ever returned.
评论 #42349097 未加载
adastra225 months ago
&gt; One core requirement for this is what Rust calls an Enum and what is broadly known as a Union type<p>Union types and enum types are not the same thing, and this misunderstanding invalidates the entire article. An enum type includes a marker which indicates which value it contains. The garbage collector would be able to read this tag value and know.
评论 #42347668 未加载
评论 #42348351 未加载
评论 #42347688 未加载
评论 #42348586 未加载
skybrian5 months ago
Yes, the Go garbage collector would need to support some new memory layouts to make certain kinds of unions efficient. A union between a double, a pointer, and small integer types (as done in languages like JavaScript) might be a good start?
评论 #42348095 未加载
mjevans5 months ago
I&#x27;ve thought about this while working with Go more frequently over the past few months.<p>Metadata. The same way shapes of functions let Go know which generic &#x27;profile&#x27; to use for a given thing are metadata. Just like when a reference to something is taken that type is compile time metadata.<p>Structure. The precise layout of structures and other data fields is also compile time metadata. They don&#x27;t even need to remain the same between versions of go, or even builds if somehow they&#x27;re randomized. That isn&#x27;t how programmer&#x27;s think (at least any who were also trained in assembly???). When I lay out a struct I do expect undersized fields to get padded, but I expect every field in order, and I&#x27;d prefer some way of forcing the issue for precise padding.<p>However, &#x27;union&#x27; of types is just syntax sugar. Give the programmer the above basics and add one more: builtin.*reshape()*. reshape() would allow any similarly shaped structures to replace the type of the reshaped item. E.G. reshape({x, y, z uint64},{x, y, z int64}, A, B) would convert a 192bit chunk of 3 ints of one type to the other. It could also convert anything else similarly.<p>That&#x27;s a trivial example, what about some private structure from a library? I&#x27;d think the unsafe package&#x27;s version should allow violation of the private field space, but the normal safe version might force the unexported fields to &#x27;pad&#x27; (inaccessible) space. I don&#x27;t think this would alter garbage collection, as that process likely has to keep it&#x27;s own track of regions of memory and places that point within them. That&#x27;s runtime (maybe compiler time sometimes?) metadata which reshape() would have to work with.<p>Generics even _sort_ of do this already when prefixed with ~type in the list of allowed types; the compiler&#x27;s allowed to use the passed thing as that type of value and the return it back the same as input... and I really don&#x27;t see why a reshape function couldn&#x27;t do the same thing.<p>There is something else though: reshape() likely needs to consume &#x2F; claim the resource, since it wouldn&#x27;t initialize anything. So maybe it needs to return the recast value to be assigned or passed somewhere and further invalidate usage of the variable past that use. Alternately it could take a single value variable and modify the type as part of it&#x27;s call (also providing the value as it&#x27;s return would be useful sometimes too).
aiono5 months ago
I don&#x27;t know what&#x27;s the point of the post is. Safe unions require compiler work? Sure who objects to that?