Go语言 如何从Protobuf枚举的字符串表示中获取它的值?

gzszwxb4  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(241)

我可以用下面的指令得到Protobuf枚举的字符串值:

str := testPB.Status_ENABLED.String()

如何执行逆操作?(从字符串中获取枚举元素)。

bgibtngc

bgibtngc1#

生成的代码有一个名为map[string]int32的Map,类型为map[string]int32。然后,您可以数值转换为实际定义的类型:

num := testPB.Status_value[str]
v := testPB.Status(num)

考虑到如果str值不存在于Map中(注意它是区分大小写的),Map查找将返回0。根据您如何定义protobuffer,0值可能被Map到一个没有“零”语义的枚举示例。这就是为什么建议将0Map到一个“未知”示例:

enum Status {
  UNKNOWN = 0;
  ENABLED = 1;
  // and so on
}

在Go语言中,如果字符串的表示形式实际上是未知的,那么下面哪一种方法可以正确地产生一个临时的零值:

v := testPB.Status(testPB.Status_value["does_not_exist"]) 
fmt.Println(v == testPB.Status_UNKNOWN) // true

1.18开始
使用泛型,可以编写可重用的代码来从字符串值构造protobuffer枚举:

func Enum[T ~string, PB ~int32](val T, pbmap map[string]int32, dft PB) PB {
    v, ok := pbmap[string(val)]
    if !ok {
        return dft
    }
    return PB(v)
}

其中:

  • 类型参数T是字符串表示,它也可以是具有底层类型字符串的类型,例如type MyEnum string
  • 参数pbmap是来自生成的protobuffer代码的<EnumName>_value
  • 类型参数PB是协议缓冲器枚举类型。

上面的函数采用PB类型的默认值(显然),以便在字符串表示无效的情况下进行回退,并且还允许对PB进行类型推断,否则PB只能用作返回类型。
用法:

type SomeEnum string

const (
    SomeEnumFoo SomeEnum = "FOO"
    SomeEnumBar SomeEnum = "BAR"
) 

func main() {
    foo := SomeEnumFoo
    v := Enum(foo, pb.SomeEnum_value, pb.SomeEnum_Foo)
    //        ^ T  ^ map[string]int32 ^ default PB value
    // v is type pb.SomeEnum
}

相关问题