如何简化switch语句

0 binary byte go switch-statement reflect

我有一个解码器函数,它需要一个字节片和 reflect.Kind并返回一个接口和一个错误。接口在代码的其他部分使用时将被断言。有没有办法简化我的 switch 语句,这样我就不必在每种情况下重复 NewReader、Read 和错误处理?

我现在所拥有的:

func decoder(byteValue []byte, t reflect.Kind) (interface{}, error) {
    switch t {
    case reflect.Int16:
        var ret int16
        buf := bytes.NewReader(byteValue)
        err := binary.Read(buf, binary.BigEndian, &ret)
        if err != nil {
            return 0, err
        }
        return ret, nil
    case reflect.Int32:
        var ret int32
        buf := bytes.NewReader(byteValue)
        err := binary.Read(buf, binary.BigEndian, &ret)
        if err != nil {
            return 0, err
        }
        return ret, nil
    }
}
Run Code Online (Sandbox Code Playgroud)

我在找什么:

func decoder(byteValue []byte, t reflect.Kind) (interface{}, error) {
    switch t {
    case reflect.Int16:
        var ret int16
    case reflect.Int32:
        var ret int32
    }
    buf := bytes.NewReader(byteValue)
    err := binary.Read(buf, binary.BigEndian, &ret)
    if err != nil {
        return ret, err
    }
    return ret, nil
}
Run Code Online (Sandbox Code Playgroud)

我知道这行不通,因为ret它只在 switch case 的范围内定义,并且在它之外丢失了。

Adr*_*ian 5

当然:

var ret interface{}
switch t {
case reflect.Int16:
    var i int16
    ret = &i
case reflect.Int32:
    var i int32
    ret = &i
}
buf := bytes.NewReader(byteValue)
// NOT &ret since ret is already an interface value containing a pointer
err := binary.Read(buf, binary.BigEndian, ret)
if err != nil {
    return ret, err
}
return ret, nil
Run Code Online (Sandbox Code Playgroud)

但是,这始终是一个痛苦的解决方案,因为返回interface{}是非常无用的 - 调用者将始终必须进行断言或类型切换或反射。在那种情况下我会做的是取值来填充而不是 a reflect.Kind- 即,它的作用是什么binary.Read

func decoder(byteValue []byte, val interface{}) error {
    return binary.Read(bytes.NewReader(byteValue), binary.BigEndian, val)
}
Run Code Online (Sandbox Code Playgroud)

当然,这不会为您节省太多重复的代码,它告诉您这binary.Read已经是一个非常干净的 API,不需要包装器。