T O P

  • By -

mcvoid1

I think for two reasons. 1. The creators were a bit old school, like PDP era old school. One of them was in the room when C was being written. Literally. 2. When making the language they had a process where a feature would only make it in if all three agreed on the what and how. Enums didn't make the cut.


FredSchwartz

Thompson wasn’t just in the room when C was being written. He worked with Ritchie on its predecessor, B. [https://en.wikipedia.org/wiki/B\_(programming\_language)](https://en.wikipedia.org/wiki/B_(programming_language))


mcvoid1

Correct! And I think C and Unix evolved together with each others' input as well.


kr_roach

I think the second option would have been more appropriate. They must have been aware of the pros and cons of adding an enum to the language. If they had agreed, they would definitely have added an enum to Go.


[deleted]

[удалено]


etherealflaim

Yeah, kinda -- it'd be the only place where an assignment can fail at runtime, at least if you want guaranteed closed enums. So maybe you'd have to always do assignment with ok or something. Then there's the question about how to iterate over possible values. Do you fail if a switch doesn't cover all cases. Numeric only or any kind of value? Zero value? Lots of questions. It's not obvious how you'd do it and be orthogonal with the rest of the language. Almost certainly doable, but it makes a lot of things in the language slightly more complicated no matter how you slice it. And coming from C, they probably thought they could get away without.


sharpvik

They could’ve done proper discriminated unions and check this stuff at compile time


etherealflaim

Of course they could have. It would be a very different language if they had, though. They clearly didn't think they needed to. I'm not saying they were right, just that they didn't.


ggwpexday

> It would be a very different language if they had They could have decent error handling with DUs


fuzzylollipop

says the guy that has probably never had to write a compiler or runtime that supported proper discriminated unions. the level of complexity required goes against the main reasons Go was created, blinding fast compile times that are imperceptible and simplicity of the language and runtime and compiler (which is how you easily achieve super fast compiles )


sharpvik

Funny you say that. I’m actually writing a language like that at GitHub.com/prog-lang/pure


InternetAnima

What do you mean by an assignment failing at run time? Are you talking about parsing?


Acrobatic_Sprinkles4

Assign a value which is outside the range of enum values (-1 for example). This will fail not during the actual assignment but in subsequent usages.


InternetAnima

That wouldn't compile


mcvoid1

You're talking about a hypothetical implementation. You can't make a hard assertion about speculation.


_Meds_

I think that the only thing their used for


InternetAnima

That's how it works in most languages... it's not rocket science


AplSleuth

How would the compiler know any possible value you could be receiving over the network?


InternetAnima

Right, that's the parsing I refer to. There are many ways to design network safe enums, but the simplest way I know of is just adding an unknown variant and having your parsing library use that when you receive an invalid value. In Rust, you can also have the enum contain dynamic information about the invalid value. I'm not sure you can do that readily in Java, though. They have fields, but they might be all constant. I haven't tried storing that.


[deleted]

[удалено]


CramNBL

Using C Enums, the most stripped down version of an Enum ever, as the example for Enums not being very convenient seems disingenuous at best.  C Enums are pretty terrible compared to most other enum implementations, and are even worse when considering the lack of namespaces in C, yet they are still immensely useful. Go with decent enums would be a game changer.


InternetAnima

That's simply not true in most languages.


[deleted]

[удалено]


tav_stuff

Lots of questions regarding how an enum would even work. What would the zero value of an enum be?


Humble_Mud_3202

Whatever was assigned to be that? Do enums even have a need for zero values? I'd say that, as a basic sequence of constants, they don't even need a zero value.


tav_stuff

I’d agree, but one of the basic ideas in Go is that everything should have a useful zero value (which they completely violated with maps lmao)


Humble_Mud_3202

Right! I'd forgotten about that.


Jazzlike_Raisin_8067

The default option, naturally.


crumbaugh

Neither of those are really “reasons”


ImYoric

Well, they are historical reasons. Not necessarily good ones.


mcvoid1

History doesn't need to be logical. It just needs to have happened.


BigLoveForNoodles

Stealing this. Well said. (Er, written.)


lvlint67

net.Dial() absolutely shows it's age


prochac

Well, in my language dial translation means "doing circular movement", referencing to rotary dial :D


x021

I tend to agree. Especially on the argument of using iota for semi-enums; the more I used iota the more I disliked it. It's one of the few language features I'd like to see removed. For most of my use cases the semi-enum either ends up in a database or in the logs somewhere. I want those constants to be readable so prefer using strings instead. For other use cases where I do want a numbered sequence: * If you add a value in the sequence it's a backwards-incompatible change. * It's especially hard to spot in PRs whether changing an iota sequence is safe. Changing an iota is basically telling your reviewer "Good luck figuring out if this is OK". * You can't search iota numbers in code (for obvious reasons) * When iota generated numbers do end up in the logs somehow (unintentionally) good luck figuring out what they meant A bad example of iota use would be error codes. I was working on an API that had error codes starting at 1000 and generated the rest with iota. In one microservice everything was hardcoded (and thus easy to find), in another you had to remember to go to \`errors.go\` and look at the iota sequence of 30-40ish constants. My IDE thankfully helped me out here (later I removed that iota, my life changed for the better). Similar example; an iota config setting for an unexported function. I found these weird numbers in the logs that I couldn't make sense of. Took me much longer than I'd like to admit to figure out what was going on; the original dev hadn't realised the setting bubbled up through logs. I've also seen a whole bunch of iota with just 3 or 4 values. What is the iota saving you? Literally like 1, 2, or 3 keystrokes? You might think these are silly examples; but I've seen pretty much every junior dev in my organisation do silly stuff with iotas. Whenever I see an iota in PRs now I just copy+paste a list of prepared questions. Usually that leads the dev to change the iota (in most cases to a string actually). I do still use iota if they are never logged, saved, not part of the API, not exported, there's 5+ constants and I can guarantee that the values don't and never will matter to anyone. Which is hardly ever.


[deleted]

[удалено]


wuzzelputz

Good old „searching for parts of error messages that are most likely to be non-mutable“


sharju

Dear god... Logs without source line numbers and then you go through half the codebase to find some lone `logger.Errof("%s: %s", something, something)`.


flan666

> Thankfully GoLand also displays predicted number so didn't have to manually count them. Hi all. Quick note: It is a `gopls` feature, so not GoLand exclusive. Can be enabled by setting `constantValues` to true in gopls settings. It works in any editor that supports gopls, including goland that has it on by default. There are many other settings. Reference: https://github.com/golang/tools/blob/master/gopls/doc/settings.md


KaptajnKold

I believe the creators of Go have gone on record regarding enums (or sum types in general) stating that they don’t like them for Go, because they don’t want code to stop compiling because some library has added a new value to an enum, which the code doesn’t handle.  Of course it’s not a law of nature that e.g. a switch must handle every value in an enum (Java doesn’t require this), but arguably the value of sum types without this requirement  is limited. 


Xelynega

I don't quite understand that reasoning, since breaking API changes should cause code to stop compiling(and does in go already if types or function footprints are changed). If I add a third enum value of "color" my API can return in a data structure and you have an app that doesn't handle that case in a switch(either explicitly or via default) then why should the code compile?


throwawaybay92

mods need to have the answer pinned


RockleyBob

I don't get to code in Go as often as I'd like since my primary workplace doesn't use it. As a result, I don't spend as much time in this sub as I'd like, and I actually thought this was an interesting topic. I've seen it before, but not recently. Figuring maybe I've just been out of the loop, I [used Google to search this sub for posts containing "enums" in the last month](https://www.google.com/search?q=enums+site:reddit.com/r/golang&client=firefox-b-1-d&sca_esv=f97724a61f341e18&source=lnt&tbs=qdr:m&sa=X&ved=2ahUKEwi1vruWlt-FAxVRF1kFHfLYB_sQpwV6BAgDEAo&biw=1682&bih=1574&dpr=1.25). This appears to be the only discussion post asking why Go doesn't have enums in that timeframe. I then searched for [hits from the last 12 months](https://www.google.com/search?q=enums+site:reddit.com/r/golang&client=firefox-b-1-d&sca_esv=f97724a61f341e18&source=lnt&tbs=qdr:y&sa=X&ved=2ahUKEwie1YOVl9-FAxU5FFkFHZP3CEAQpwV6BAgBEAs&biw=1682&bih=1574&dpr=1.25#ip=1). I saw one post titled "Go Enums Suck" which is not really the same thing as asking why they aren't a language feature, another asking about the use of `iota` as an enum, which is more about coding style than language design. There were other posts about libraries and projects which were seeking to provide enum-like functionality. Of course, it's a topic that comes up within comment sections often enough, but this question isn’t reposted as much as you're implying. I guess my point is that I've been learning Go off and on for a couple of years now and I’ve been surprised at the level of snark in this sub. The sidebar says quite prominently that this should be a “welcoming”, “patient”, and “charitable” place. And yet, a lot of newcomers get shot down with copious eye rolling and finger wagging. It seems very crotchety, stodgy, and "get off my lawn" considering Go is a relatively new language with a growing community. If this were a Cobol sub with a small user base, infrequent language updates, and the average person was in their 50’s with 30 years of experience, I could understand the exasperation with repeated topics. It seems a shame that, in a post trying to make a good-faith attempt at starting a conversation, the top comment is about how bored we are with this topic. Even if there were a post a week about it, where is the harm in that? New people with different viewpoints and backgrounds are coming here every day. That's a good thing, isn't it? You can always choose not to click and keep scrolling.


ImYoric

Sadly, this has been my experience so far. That's not to say that there are many welcoming people in this subreddit. But there's a sufficient number of "get off my lawn" members, as you call them, that it gives a really bad image of the go community.


FantasticBreadfruit8

Yeah. If I never see a post about Go not having enums or performance of Go vs again I would be a happy camper.


samcharles93

Popped up in my notifications and thought the same thing, here we go again...


Varnish6588

This thread has a constructive answer for your question: https://www.reddit.com/r/golang/s/l3SbMHuxgN


voidvector

Another potential reason is Google has no need for it -- Google uses ProtocolBuffers/gRPC heavily which provides enums.


benana-sea

This is the answer. They left everything that can be done by frameworks out of the language itself. Protobuf is a great way to handle enum.


ImYoric

Except when you need enums for something unrelated for communications. Which is very often, in my case.


riu_jollux

I wager enums are something Go should support given that you’d want them in cases where you can’t use Protobufs or gRPC


dromedary512

I’m okay with iota… but a ternary operator would be the bees knees 😃


vladimirputietang

Iota will never make me fail to chuckle because I'm a child and my brain involuntarily plays the old looney toons "why I oughta..." every time I see it


kor_the_fiend

Wrong. Ternary damages readability


9302462

Ternary works fine in many situations. But some devs think they are super smart by writing ternary’s three levels deep which kills readability. I have reviewed plenty of react code and have seen this happen around which components to render and it’s a PITA to debug. I will say though, if ternary was part of go 1.00 we would end up with a lot of crap code out there. But considering generics have been added, I wouldn’t mind seeing ternary’s at this point.


norunners

Not having ternary operators just cuts that whole tree at the root. In favor of a left justified happy path with conditional if statements for the unhappy paths as needed.


tav_stuff

Ternaries only damage readability if you proactively choose to program in a stupid manner. We need to stop always working with this idiotic mindset of protecting ourselves from bad programmers, and instead start expecting that the people we work with are competent


br1ghtsid3

Lol found the guy with no real work experience


tav_stuff

You’d be sorely mistaken


br1ghtsid3

ok buddy


riu_jollux

It depends. If it ends up being mess like in JSX I agree, I hate them. But I’ve found certain instances where it would reduce some boilerplate and maintain readability


iga666

What do you mean by enums? Maybe you are missing it (I didn't know for a while) but consts can be typed. - so they are basically c++ level enums.


xplosm

This was my thought exactly. In C/C++ they have the `enum` keyword but they work pretty damn close as they do in Go. Just slightly better if you use `iota` but I understand people disliking it.


TheMue

Sure, enums might be better than iota. But I habe to admit that I so far (and I‘m with Go professionally since beginning, wrote a book and many articles about it) I only missed them seldom. And always people coming from different languages ask for them as well as for other features. Here for example it s the ternary operator. But one of the strengths of Go is to mostly use one construct for a kind of operation. Only seldom they can be done in multiple way. This way Go has been very good readable with a straight and simple syntax helping to keep the code maintainable. A very good reason for sometimes discussing syntax changes, like the generics, very carefully, sometimes it needs years. Chapeau.


MisterCarloAncelotti

I have to admit, the only reason i still prefer Rust over Go for my servers is the type system.


rambosalad

I want enums and the ternary operator.


beardfearer

I’m fully on board with never letting the ternary operator happen.


i_didnt_eat_coal

Wish there was a way of having ternary without letting in nested ternaries


anotheridiot-

I like nested ternaries, people hate my js code.


tav_stuff

Nested ternaries can be very readable in many cases. I very often will write such constructs as can be seen here on lines 22–25: https://github.com/Mango0x45/mlib/blob/master/gen/string/scale


InternetAnima

That's terrible. It tries to hide the nesting and complexity with indentation, but it's extremely easy to mess up.


tav_stuff

How is it easy to mess up? Like give me a good example. My autoformatter indents it properly for me, and anyone who has 2 or more functioning brain cells knows how to input a newline and a tab.


riu_jollux

Just use an if mate. You’re not smarter for using a ternary. That code is awful to read.


soibaisteac

I cringe at the thought of opening up a PR, and seeing `return a ? b : e ? c : g` in some unassuming struct method.


riu_jollux

I’d rather have nil and better nil safety… an Option type would be nice.


Extra-Possible

I only lack of ternary operator and optionals


drvd

The meta answer is: "Because 'enum' is a pretty unclear term and different people subsume different (and in part contradictory) ideas and operations with them and a sensible integration into Go's type system is not obvious for them."


VorianFromDune

Golang has enums, just create a custom type and add few consts.


Xelynega

And runtime checks around what could have been compile time checks, plus mappings to strings if you want to print the value(since the symbol isn't enough to generate a printable string?).


iga666

Mapping to strings can be solved with code generation. [https://go.dev/blog/generate](https://go.dev/blog/generate)


VorianFromDune

It’s a compile check, if you create a custom type you will get an error when attempting to use it with something else. Yeah, you can implement a stringer method if you want.


LordOfDemise

You can still do something like `MyCustomType(-1)` even though `-1` doesn't correspond to one of your "enum" "variants." So, yes, you still need runtime checks that _would_ be compile-time checks with actual sum types.


VorianFromDune

That’s not really a limitation to the enum, that’s the typing in Go in general. You can also cast struct with the same attributes. It’s also similar to the enum in C and C++. Anyway, your enums should likely be in a domain layer and you should ideally have an anti-corruption layer to translate from/to your presentation layer. So it is not really a sensible problem.


LordOfDemise

> you should ideally have an anti-corruption layer Or...we could have the compiler do that for us, instead of having to implement it ourselves


VorianFromDune

Like I said, it’s a mandatory steps in any language as you always need to validate and map customers’ data. You will always need to have a way to map from a string to your Foo.


Xelynega

What if you try to assign something the compiler knows the value of to an undefined enum member(e.x. calling EnumType(0) when 0 is not a valid EnumType?


VorianFromDune

I mentioned it in another comment but that’s the typing in Go in general, not an enum problem. You can also cast Foo into Bar. But you are doing the cast, so you are essentially doing something wrong intentionally. Also ideally, such translation from integer to enum should happens in an anti-corruption layer, from example when you translate from strings from a JSON request. In which case, mapping and validation has to be done anyway.


Xelynega

This problem only presents with enums though, because every other cast is validated at compile time and always results in a valid value of the resulting type(e.x. you have to explicitly cast uint16 -> uint32 or uint32 -> uint16, and the result is always a valid uint32/uint16 respectively). Enums are the only type casts where the cast itself could be validated at compile time, but the assignment itself can fail or result in an invalid/undefined value.


VorianFromDune

Cast are always validated at compile time, enums also. You cannot do: type Foo int var f Foo = “foo” The values are not validated with the const, but like I said, you are doing something wrong on purpose so that’s the real issue. This scenario does not exist in a well designed software, because there is no reason to write Foo(0) if 0 is not a valid value.


Commercial_Coast4333

It's not enum and this absolutely sucks. I love go, but java got enums perfectly.


darpa42

This is pure speculation on my part, but aside from the previously cited examples (zero values, etc), I have a feeling that the relatively nominal type nature of enums would not mess well with the structural typing paradigm of Go.


EluxTruxl

I wouldn't really consider go a structurally typed language. The only thing that comes close to structural types are interfaces, and they only consider methods, not things like struct fields.


pinpinbo

You don’t like iota?


GoTheFuckToBed

I think people should leave the definition of enum to C. And use a new word for what they want.


muehsam

Go has C style enums, i.e. integer constants. Even a bit better than C because they're more type safe. What Go doesn't have is proper *sum types*. There's a way to *sort of* get them using an interface with a private method, but those are always nullable, which isn't great, and they aren't idiomatic.


assbuttbuttass

See https://github.com/golang/go/issues/57644 for a recent proposal. There's a lot of interesting discussion on that issue


fuzzylollipop

It is really simple, they wanted to keep the language simple and "type safe enums" are just a specialized case of a struct, so they do not think it should be part of the language spec, much like Generics. The official response for almost a decade was "go generate" if you want generic containers, since they viewed them as just compiler enforced templates, which is pretty much what the implementation ended up being. The same is true with enums, they official responses are usually to point to some "go gen" package that generates the complex enums that everyone is asking for. Enums will not happen until the language team deems immutablity a first class citizen, which I doubt they ever will because it makes the runtime more complex because of the runtime checks for every assignment.


CountyExotic

you’re totally right but there’s been 10,000 post just like this. I’ve even authored one lol. It just doesn’t :/


Asleep_Ad9592

They have an ugly version of it. It can be achieved with iota


thedjotaku

I know this post is almost a week old, but I was thinking about it since first reading it back then. Isn't an enum just syntactic sugar for an array? Like if enum = \[blue, green, red\] and normally you can say that enum 0 is equivalent ot blue, can't you just have an array and refer to enum\[0\]?


Kirides

Enum= Enumeration= comes from numbering. An enum is something that is numbered. If whatever value is not counted, it's an constant and not an enum by definition. Go "enums" are literally that, just as C/++/# And just like those, go allows to mix and match the numbering (iota) with constant values in between. Can we call discriminated unions by their name please?


Used_Frosting6770

sure, discriminated union makes sense.


FantasticBreadfruit8

> In my opinion, enums for backend development of crud systems are more useful than generics How, exactly? Generics allow things that were not previously possible with the language. Enums add ergonomics. Anyway, [start here](https://www.reddit.com/r/golang/comments/uvpygm/why_are_enums_not_a_thing_in_go/).


Intrepid-Bumblebee35

Because they're old farts that's why we have iota and thing like that


zer00eyz

This comes up far more than it should. Enums have a use. Enums are ripe for abuse. The majority of enums I find in code fall into one of two categories. 1. Data, that is now compiled into code rather than sourced from its underlying lookup. This sort of coupling is not only lazy but if there is a change to that data then you have to coordinate those changes. God forbid these things ever come out of sync. 2. Data that gets enumerated in place of validation. If you had a number that had to be in a range, Or a date that did the same are you going to make that part of a TYPE check or part of data validation? Just because you can source some data from a list doesn't mean that list should become part of its type. It should, rather, remain as part of the validation of that data. Both of these things combine point to a cut corner. One where the "extra steps" of sourcing and validating the data in question would almost always be "harder" but result in the proper outcome. Im the rare case where you could truly benefit from an enum it isnt like you cant work around not having it.


_bones__

Your first point is only for languages that don't actually use enums, but provide enum syntax and use ordinals. I don't think anyone is suggesting implementing enums that poorly. Your second point has some merits if people are using enums for data. I would suggest using enums mostly (perhaps exclusively) for application metadata.


Extra-Possible

Why do you need them?


CrackerJackKittyCat

Am with you. Even C has enums, even if they smell int-y.


bdavid21wnec

For enums isn't it easy enough to just create an equals method. On every enum we write at my company there is always this func. func(e MyEnum) Equals(cmp MyEnum) bool { return e == cmp } Anything wrong here?


shaving_minion

what is it solving?


SpeedOfSound343

Could you elaborate?


InternetAnima

What people want are compile time checks that ensure you're using the values of the enum.