31

I understand that the idiomatic way to create an enum in GO is as follows:

type topicStatus int

const (
  registered topicStatus = iota
  active
  inactive
  pendingRemoval
  removed
 )

but if I have another "enum" that wants to "reuse" a name, I get an error:

type hotelVisit int

const (
   registered hotelVisit = iota
   checkedIn
   checkedOut
)

Here, if I try this, I cannot differentiate between topicStatus.registered and hotelVisit.registered as "registered" was previously used - is there a way to "namespace" the "enum" names?

0

3 Answers 3

18

Polluting the namespace with numerous common word lower case identifiers that are likely to cause naming conflicts isn't something I'd consider idiomatic Go. Same goes for creating packages just to hold a handful of constant declarations.

I'd probably do something like this:

type topicStatus int

const (
    tsRegistered topicStatus = iota
    tsActive
    tsInactive
    tsPendingRemoval
    tsRemoved
)

type hotelVisit int

const (
    hvRegistered hotelVisit = iota
    hvCheckedIn
    hvCheckedOut
)

Now you can declare and initialize with ts := tsPendingRemoval. Clear and concise with little risk of naming conflicts.

Sign up to request clarification or add additional context in comments.

4 Comments

building on top of this proposal, you even don't have to give up stringer for string code generation: //go:generate stringer -type=topicStatus -trimprefix=ts
This smells like hungarian notation. I know it's a hotelVisit. It says so right there. When I type registered, my type hinting tells me it is. When I'm in a context requiring a hotelVisit, of course it's a hotelVisit.
I agree with @AdamBarnes this smells like hungarian notation. And other code I have seen puts the hole name in front of each constant such as HotelVisitRegistered, HotelVisitCheckedIn and this becomes very wordy.
but this isnt javascript. The compiler will let you know, immediately, if you are trying to create a name conflict. So there are no hidden dangers or bugs. Also a package "is" a namespace, by definition. So whenever you are worrying about naming conflicts, package is precisely the tool design to solve the situation.
14

Create a new package for each of the enums you want to define. This means creating a sub-directory with a go file the has "package topicStatus" with the const definition inside (sub-directory name is the same as the package name). Remember all the constants defined must be upper case so they are exportable. Do the same for "hotelVisit" and whatever you need. Your program will import these packages and then use them as needed: hotelVisit.Registered, topicStatus.Registered.

Comments

11

One workaround is to use an anonymous struct to define a namespace.

    type TopicStatusType int
    const (
       registered topicStatus = iota
       active
       ...
    )
    var TopicStatus = struct{
        Registered TopicStatusType
        Active TopicStatusType
        ...
    }{
        Registered: registered,
        Active: active,
        ...
    }

3 Comments

why is this not the answer? Couldn't the accepted answer potentially lead to circular dependencies if declared in the same package
This hack indeed works... but it comes with the inconvenience that you have to type each identifier 4 times.
And someone can change your values

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.