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

时间:2019-01-23 00:57:04

标签: go

卡住了。

我正在尝试找出如何使用go枚举从const中获取位掩码值。例如,如果密钥为5,即0101位,则为狗和鱼。获取位值(1、2、4、8、16、32、64等)的最简单方法是什么,以便我可以选择字符串值并返回一组动物?

type Key int

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

曾经阅读,但我无法解决。

2 个答案:

答案 0 :(得分:4)

声明一片字符串,其中字符串与常量名称相对应:

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

要获取位的名称,请遍历名称。如果设置了相应的位,则将名称添加到结果中:

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

如果将常量更改为位索引而不是位值,则可以使用stringer实用程序来创建func (k Key) String() string。这是此更改的代码:

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
}

答案 1 :(得分:0)

用 iota 创建位掩码值 Iota 在创建位掩码时非常有用。例如,为了表示可能是安全的、经过身份验证的和/或准备好的网络连接的状态,我们可能会创建一个如下所示的位掩码:

package main

import "fmt"

const (
    Secure = 1 << iota // 0b001
    Authn              // 0b010
    Ready              // 0b100
)

// 0b011: Connection is secure and authenticated, but not yet Ready

func main() {
    ConnState := Secure | Authn
    fmt.Printf(`    Secure:    0x%x (0b%03b)
    Authn:     0x%x (0b%03b)
    ConnState: 0x%x (0b%03b)
    `, Secure, Secure, Authn, Authn, ConnState, ConnState)
}