Go:安全地将整数转换为 Protocol Buffer 枚举值的最佳实践

标签 go enums type-conversion protocol-buffers

我在 proto 文件中有一个枚举,它在 pb.go 文件中生成整数常量。我现在有一些来自外部数据源的整数,并希望将它们安全地映射到可能的常量。

这是我目前拥有的:https://play.golang.org/p/-5VZqPbukd

package main

import (
    "errors"
    "fmt"
)

//enum in the proto file
//
// enum X {
//    A = 0;
//    B = 1;
//    C = 2;
//    D = 3;
// }

//enum type generated by protoc
type X int32

//enum constants generated by protoc
const (
    X_A X = 0
    X_B X = 1
    X_C X = 2
    X_D X = 3
)

func intToX(v int) (X, error) {
    x := X(v)
    switch x {
    case X_A, X_B, X_C, X_D:
        return x, nil
    }
    return 0, errors.New("could not convert int to X")
}

func main() {
    for i := -1; i < 10; i++ {
        if x, err := intToX(i); err != nil {
            fmt.Println("unhandled error:", err, "for input value", i)
        } else {
            fmt.Printf("%d => X(%d)\n", i, x)
        }
    }
}

问题:是否有更好、更惯用的方法将传入的整数值映射到协议(protocol)生成的常量?

特别是,我想避免在 case A, B, C, D 语句中显式列出所有常量。

最佳答案

我不知道您使用的是哪个原型(prototype)生成包,但是使用 github.com/golang/protobuf/proto 您还可以获得枚举的反向映射。

示例 xyz.pb.go 生成的文件:

type TimeInterval int32

const (
    TimeInterval_TI_UNKNOWN TimeInterval = 0
    TimeInterval_TI_HOUR    TimeInterval = 1
    TimeInterval_TI_DAY     TimeInterval = 2
    TimeInterval_TI_WEEK    TimeInterval = 3
    TimeInterval_TI_MONTH   TimeInterval = 4
    TimeInterval_TI_QUARTER TimeInterval = 5
    TimeInterval_TI_YEAR    TimeInterval = 6
)

var TimeInterval_name = map[int32]string{
    0: "TI_UNKNOWN",
    1: "TI_HOUR",
    2: "TI_DAY",
    3: "TI_WEEK",
    4: "TI_MONTH",
    5: "TI_QUARTER",
    6: "TI_YEAR",
}
var TimeInterval_value = map[string]int32{
    "TI_UNKNOWN": 0,
    "TI_HOUR":    1,
    "TI_DAY":     2,
    "TI_WEEK":    3,
    "TI_MONTH":   4,
    "TI_QUARTER": 5,
    "TI_YEAR":    6,
}

func (x TimeInterval) String() string {
    return proto.EnumName(TimeInterval_name, int32(x))
}
func (TimeInterval) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

因此,您可以通过以下方式测试是否存在:

if _, found := TimeInterval_name[testinputint]; found{
    //all ok
} else {
   //not a value for this enum
}

关于Go:安全地将整数转换为 Protocol Buffer 枚举值的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38957169/

相关文章:

java - JPA/Hibernate - 将枚举保留为常量表

object - Monotouch:将对象转换为NSObject

string - 根据语言环境将货币/浮点字符串解析为浮点类型

rest - 如何在 golang 中处理未设置值的补丁请求

c++ - 可变函数导致带有枚举的 SIGILL 信号

enums - 如何为枚举实现 Borrow、ToOwned 或 Deref?

c - "int i = 1;Why (i >= 60 * 60 * 1000/1 * 1000)"是真的吗?

go - 运行线程一定时间 - 在被杀死之前

go - 尝试将数据解码到 golang 中的界面

docker - 在 docker 构建期间不能 `go get` 依赖项