4 ms·
> my main use case for enums is for APIs and database designs, where I want to lock down some field to a set of acceptable values and make sure anything else is
by randomdata 2y ago
> my main use case for enums is for APIs and database designs, where I want to lock down some field to a set of acceptable values and make sure anything else is a mistake
Then what you are really looking for is sum types (what Rust calls enums, but unusually so), not enums. Go does not have sum types, but you can use interfaces to archive a rough facsimile and most certainly to satisfy your specific expectation:
type Hot struct{}
func (Hot) temp() {}
type Cold struct{}
func (Cold) temp() {}
type Temperature interface {
temp()
}
func SetThermostat(temperature Temperature) {
switch temperature.(type) {
case Hot:
fmt.Println("Hot")
case Cold:
fmt.Println("Cold")
}
}
- blueberry87 2y agoannoyingly go can't have proper sum types, as the requirement for a default value for everything doesn't make any sense for sum types
- andyferris 2y agoYou can just default to the first variant, no?
- throwaway143829 2y agoCouldn't the zero value be nil? I get that some types like int are not nil-able, but the language allows you to assign both nil and int to a value of type any (interface{}), so I wonder why it couldn't work the same for sum types. i.e. they would be a subset of the `any` type.
- randomdata 2y agoSaid "requirement" is only a human construct. The computer doesn't care. If the humans choose to make an exception for that, it can be done. Granted, the planning that has taken place thus far has rejected such an exception, but there is nothing about Go that fundamentally prevents carving out an exception.
- throwaway143829 2y agoEnums and sum types seem to be related. In the code you wrote, you could alternatively express the Hot and Cold types as enum values. I would say that enums are a subset of sum types but I don't know if that's quite right. I guess maybe if you view each enum value as having its own distinct type (maybe a subtype of the enum type), then you could say the enum is the sum type of the enum value types?
- randomdata 2y ago> Enums and sum types seem to be related. They can certainly help solve some of the same problems. Does that make them related? I don't know. By definition, an enumeration is something that counts one-by-one. In other words, as is used in programming languages, a construct that numbers a set of named constants. Indeed you can solve the problem using that: type Temperature int const ( Hot Temperature = iota Cold ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } But, while a handy convenience (especially if the set is large!), you don't even need enums. You can number the constants by hand to the exact same effect: type Temperature int const ( Hot Temperature = 0 Cold Temperature = 1 ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } I'm not sure that exhibits any sum type properties. I guess you could see the value as being a tag, but there is no union.
- lelanthran 2y agoUnfortunately, this: const ( Hot Temperature = 0 Cold Temperature = 1 ) Isn't really a good workaround when lacking an enumeration type. The compiler can't complain when you use a value that isn't in the list of enumerations. The compiler can't warn you when your switch statement doesn't handle one of the cases. Refactoring is harder - when you add a new value to the enum, you can't easily find all those places that may require logic changes to handle the new value. Enums are a big thing I miss when writing Go, compared to when writing C.