英文:
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 uint8
和field.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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论