0

我有一个解码器函数,它接受一个字节切片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
    }
}

我在找什么:

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
}

我知道这不会起作用,因为ret仅在 switch 案例的范围内定义并且在它之外丢失了。

4

1 回答 1

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

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

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

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

于 2019-12-16T17:18:00.920 回答