GoLang: Reading and casting bytes into struct fields

huangapple go评论81阅读模式
英文:

GoLang: Reading and casting bytes into struct fields

问题

我正在从io.Reader中逐个字段地读取到一个结构体中。

// structFields 返回一系列 reflect.Value
for field := range structFields {
    switch field.Kind() {
    case reflect.String:
        // 省略
    case reflect.Uint8:
        value := make([]byte, 2)
        reader.Read(value)

        var num uint8
        err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, &num)
        if err != nil { return err }
        field.SetUint(int64(num))
    // 省略其他 uint 和 int 类型的 case 语句
    }
}

不幸的是,对于每个 Uint 和 Int 数据类型,都需要重复 reflect.Uint8 的代码块,因为我需要在每种情况下正确创建 var num

有没有办法简化这个 switch 语句?

英文:

I am reading from an io.Reader into a Struct, field by field.

// structFields returns a sequence of reflect.Value
for field := range structFields {
    switch field.Kind() {
    case reflect.String:
        // Omitted
    case reflect.Uint8:
        value := make([]byte, 2)
        reader.Read(value)

        var num uint8
        err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, &num)
        if err != nil { return err }
        field.SetUint(int64(num))
    // Case statements for each of the other uint and int types omitted
    }
}

Unfortunately the block for reflect.Uint8 needs to be repeated for each of the Uint and Int data types since I need to create the var num correctly in each case.

Is there a way I can simplify this switch statement?

答案1

得分: 2

不使用var num uint8field.SetUint(int64(num)),而是将指向结构字段的指针传递给binary.Read

ptr := field.Addr().Interface()
err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, ptr)

并将case语句修改为:

case reflect.Uint8, reflect.Int, reflect.Uint, ...:

然后,您需要处理不同大小的数字。幸运的是,您可以直接将读取器传递给binary.Read,它会自动处理:

err := binary.Read(reader, binary.LittleEndian, ptr)

最后,正如FUZxxl所说,您可以直接将整个结构的指针传递给binary.Read,它会为您处理所有这些。

英文:

Instead of using var num uint8 and field.SetUint(int64(num)) just pass a pointer to the struct field to binary.Read:

ptr := field.Addr().Interface()
err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, ptr)

And make the case statement say:

case reflect.Uint8, reflect.Int, reflect.Uint, ...:

Then you need to deal with differently-sized numbers. Fortunately you can just pass your reader directly to binary.Read and it'll take care of it:

err := binary.Read(reader, binary.LittleEndian, ptr)

Finally, as FUZxxl says, you can just pass a pointer to the entire struct to binary.Read and it'll do all this for you.

huangapple
  • 本文由 发表于 2014年7月23日 05:37:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/24898304.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定