dpglo66848 2016-08-15 14:34
浏览 71
已采纳

开始:安全地将整数转换为协议缓冲区枚举值的最佳实践

I have an enum in a proto file that generates to integer constants in the pb.go file. I now have some integers coming from the an external data source and want to safely map them to the possible constants.

Here is what I currently have: 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)
", i, x)
        }
    }
}

Question: Is there a better, more idiomatic way to map incoming integer values to protoc-generated constants?

In particular, I would like to avoid listing all constants explicitly in the case A, B, C, D statement.

  • 写回答

2条回答 默认 最新

  • doutiaoku4495 2016-08-15 16:11
    关注

    I do not know which proto generation package you are using, but with github.com/golang/protobuf/proto you also get the reverse mapping of enums.

    Example xyz.pb.go generated file:

    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} }
    

    So with this you could test for existence in the following manner:

    if _, found := TimeInterval_name[testinputint]; found{
        //all ok
    } else {
       //not a value for this enum
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看