在Go中使用位掩码(使用iota进行枚举)

Bit stuck.

I'm trying to work out how to get the bitmask values from a const with go enumeration. For example, if key is 5, which is 0101 bits, it would be dog and fish. What is the easiest way to get the bit values (1,2,4,8,16, 32, 64 etc) so I can select the string values and return the set of animals?

type Key int

const (
    Dog Key = 1 << iota
    Cat
    Fish
    Horse
    Snake
    Rabbit
    Lion
    Rino
    Hedgehog
)

Been reading but I can't work this out.

Declare a slice of strings where the strings correspond to the constant names:

var animalNames = []string{
    "Dog",
    "Cat",
    "Fish",
    "Horse",
    "Snake",
    "Rabbit",
    "Lion",
    "Rino",
    "Hedgehog",
}

To get the names for the bits, loop through the names. If the corresponding bit is set, add the name to the result:

func Names(k Key) []string {
    var result []string
    for i := 0; i < len(animalNames); i++ {
        if k&(1<<uint(i)) != 0 {
            result = append(result, animalNames[i])
        }
    }
    return result
}

Run it on the playground.

If you change the the constants to be bit indexes instead of bit values, then you can use the stringer utility to create a func (k Key) String() string. Here's the code for this change:

type Key uint

const (
    Dog Key = iota
    Cat
    Fish
    Horse
    Snake
    Rabbit
    Lion
    Rino
    Hedgehog
)

//go:generate stringer -type=Key

func Names(k Key) []string {
    var result []string
    for animal := Dog; animal <= Hedgehog; animal++ {
        if k&(1<<animal) != 0 {
            result = append(result, animal.String())
        }
    }
    return result
}