type Test int
const (
T1 Test = 0
T2 = 1
)
func TestSomething(t Test) {}
...
TestSomething(17)
So this isn't a good suggestion, because you can easily pass any int value and will not get a compiler error. You may as well be using strings at that point. package main
import "fmt"
type Test int
const (
T1 Test = 0
T2 = 1
)
func main() {
t, err := TestString("T1")
if err != nil {
panic(err)
}
TestSomething(t)
}
func TestSomething(t Test) {
fmt.Println(t.String())
}
Having said that, it seems weird to have to mimic enums, as opposed to actually having it. Doesn't feel like it would add much complexity, if at all.Like C or C++ do? :)
Other languages take a stricter approach, and maybe that's better. Not defending (although I like Go), but it's really more a language philosophy than a singular defect.
As the other commenter noted, this should fail code review and you should be using the provided constants, and it should be clear to you. And if you disagree (which again is totally valid), you should use a stricter language—there's plenty out there!
I see your point however.
Also:
variableDefinedInAFarAwayModule := 17
...
TestSomething(variableDefinedInAFarAwayModule)
It's not always as clear as a constant value being passed to an incorrect type.variableDefinedInAFarAwayModule is definitionally type int and will not be cast. It is also unpublished, so you couldn't be using it for a faraway module?
Your 17 in the previous example has it's typed determined at compile time which is why it can be a problem.
TestSomething(T1 & T2)Int types also don't give you any guards when deserializing.
Create a new int type and use that for your enums. While you still can create an illegal enum value, you basically have to be looking for trouble. It’s not going to happen accidentally. It’s even harder if it’s an unpunished type in a different package.
See:
https://github.com/donatj/sqlread/blob/91b4f07370d12d697d18a...