如何将二进制文件读入结构体并使用反射 – Go语言

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

How to read a binary file into a struct and reflection - Go Language

问题

我正在尝试编写一个程序,将二进制文件读入到Golang中的结构体中。我的方法是使用binary包读取二进制文件,并将其填充到包含数组的结构体中。我使用数组而不是切片,因为我想指定字段的长度。这似乎工作得很好,但是当我尝试使用反射打印字段的值时,出现了以下错误:

panic: reflect: call of reflect.Value.Bytes on array Value

以下是代码:

  1. package main
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "log"
  6. "os"
  7. "reflect"
  8. )
  9. type SomeStruct struct {
  10. Field1 [4]byte
  11. Field2 [2]byte
  12. Field3 [1]byte
  13. }
  14. func main() {
  15. f, err := os.Open("/Users/user/Downloads/file.bin")
  16. if err != nil {
  17. log.Fatalln(err)
  18. }
  19. defer f.Close()
  20. s := SomeStruct{}
  21. err = binary.Read(f, binary.LittleEndian, &s)
  22. numOfFields := reflect.TypeOf(s).NumField()
  23. ps := reflect.ValueOf(&s).Elem()
  24. for i := 0; i < numOfFields; i++ {
  25. value := ps.Field(i).Bytes()
  26. for j := 0; j < len(value); j++ {
  27. fmt.Print(value[j])
  28. }
  29. }
  30. }

当我将代码更改为以下内容时:

  1. package main
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "log"
  6. "os"
  7. "reflect"
  8. )
  9. type SomeStruct struct {
  10. Field1 [4]byte
  11. Field2 [2]byte
  12. Field3 [1]byte
  13. }
  14. func main() {
  15. f, err := os.Open("/Users/user/Downloads/file.bin")
  16. if err != nil {
  17. log.Fatalln(err)
  18. }
  19. defer f.Close()
  20. s := SomeStruct{}
  21. err = binary.Read(f, binary.LittleEndian, &s)
  22. numOfFields := reflect.TypeOf(s).NumField()
  23. ps := reflect.ValueOf(&s).Elem()
  24. for i := 0; i < numOfFields; i++ {
  25. value := ps.Field(i)
  26. fmt.Print(value)
  27. }
  28. }

它会打印出数组的ASCII表示形式,我需要打印ASCII的字符表示形式,这就是我遇到panic的原因。

你有什么想法吗?

英文:

I am trying to write a program to read a binary file into a struct in golang, the approach is to use the binary package to read a binary file to populate a struct that contains arrays, I am using arrays and not slices because I want to specify the field length, this seems to work fine but when I try to use reflection to print our the values of the fields I am getting this error

panic: reflect: call of reflect.Value.Bytes on array Value

Here is the code

  1. package main
  2. import (
  3. &quot;encoding/binary&quot;
  4. &quot;fmt&quot;
  5. &quot;log&quot;
  6. &quot;os&quot;
  7. &quot;reflect&quot;
  8. )
  9. type SomeStruct struct {
  10. Field1 [4]byte
  11. Field2 [2]byte
  12. Field3 [1]byte
  13. }
  14. func main() {
  15. f, err := os.Open(&quot;/Users/user/Downloads/file.bin&quot;)
  16. if err != nil {
  17. log.Fatalln(err)
  18. }
  19. defer f.Close()
  20. s := SomeStruct{}
  21. err = binary.Read(f, binary.LittleEndian, &amp;s)
  22. numOfFields := reflect.TypeOf(s).NumField()
  23. ps := reflect.ValueOf(&amp;s).Elem()
  24. for i := 0; i &lt; numOfFields; i++ {
  25. value := ps.Field(i).Bytes()
  26. for j := 0; j &lt; len(value); j++ {
  27. fmt.Print(value[j])
  28. }
  29. }
  30. }

when I change the code to this

  1. package main
  2. import (
  3. &quot;encoding/binary&quot;
  4. &quot;fmt&quot;
  5. &quot;log&quot;
  6. &quot;os&quot;
  7. &quot;reflect&quot;
  8. )
  9. type SomeStruct struct {
  10. Field1 [4]byte
  11. Field2 [2]byte
  12. Field3 [1]byte
  13. }
  14. func main() {
  15. f, err := os.Open(&quot;/Users/user/Downloads/file.bin&quot;)
  16. if err != nil {
  17. log.Fatalln(err)
  18. }
  19. defer f.Close()
  20. s := SomeStruct{}
  21. err = binary.Read(f, binary.LittleEndian, &amp;s)
  22. numOfFields := reflect.TypeOf(s).NumField()
  23. ps := reflect.ValueOf(&amp;s).Elem()
  24. for i := 0; i &lt; numOfFields; i++ {
  25. value := ps.Field(i)
  26. fmt.Print(value)
  27. }
  28. }

it prints the arrays with their ascii representation, I need to print the char representation of the ascii and that when I get the panic

thoughts?

答案1

得分: 2

Bytes 文档中提到:

Bytes 返回 v 的底层值。如果 v 的底层值不是一个字节切片,则会引发 panic。

将数组切片化以获取字节切片:

  1. field := ps.Field(i)
  2. value := field.Slice(0, field.Len()).Bytes()
  3. for j := 0; j < len(value); j++ {
  4. fmt.Print(value[j])
  5. }

你也可以通过迭代数组来实现:

  1. value := ps.Field(i)
  2. for j := 0; j < value.Len(); j++ {
  3. fmt.Print(byte(value.Index(j).Uint()))
  4. }
英文:

The Bytes documentation says:

> Bytes returns v's underlying value. It panics if v's underlying value is not a slice of bytes.

Slice the array to get a slice of bytes:

  1. field := ps.Field(i)
  2. value := field.Slice(0, field.Len()).Bytes()
  3. for j := 0; j &lt; len(value); j++ {
  4. fmt.Print(value[j])
  5. }

You can also iterate through the array:

  1. value := ps.Field(i)
  2. for j := 0; j &lt; value.Len(); j++ {
  3. fmt.Print(byte(value.Index(j).Uint()))
  4. }

huangapple
  • 本文由 发表于 2022年3月30日 01:39:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/71666528.html
匿名

发表评论

匿名网友

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

确定