我在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)
}
}
}
问题:是否有更好的,更惯用的方法将传入的整数值映射到protoc生成的常量?
特别是,我想避免在case A, B, C, D
语句中明确列出所有常量。
答案 0 :(得分:0)
是的,因为@RickyA提到使用范围很好,因为它验证了所有可能的底层const值。
此外,您可以检查枚举的长度,但这只有在基础枚举值没有任何“间隙”的情况下才有可能。并且有一个连续的数字范围。
通过代码详细说明:
typelength := int32(len(TimeInterval_name))
if testinputint < 0 || int32(testinputint) >= typelength {
// not a value for this enum, return err
}
稍微冗长一点,只使用int而不是int32
if testinputint < 0 || int(testinputint) >= len(TimeInterval_name) {
// not a value for this enum, return err
}
但是如上所述,这只适用于坚持适当的iota的枚举。当你改变你的枚举来读取这样的东西时可能不是这样的:
var TimeInterval_name = map[int32]string{
0: "TI_UNKNOWN",
1: "TI_HOUR",
2: "TI_DAY",
3: "TI_WEEK",
// we do not use month anymore 4: "TI_MONTH",
5: "TI_QUARTER",
6: "TI_YEAR",
}
因为生成的地图的长度明显少于6:)
换句话说,使用上面找到的@Ricky_A方法来保证安全。