繁体   English   中英

Go 使用反射将字节复制到结构字段中

[英]Go copy bytes into struct fields with reflection

我如何遍历字节切片并将它们分配给结构的字段?

type s struct {
  f1 []byte
  f2 []byte
  f3 []byte
}

func S s {
  x := s{}
  x.f1 = make([]byte, 4)
  x.f1 = make([]byte, 2)
  x.f1 = make([]byte, 2)
  return x
}

func main() {
  data := []byte{83, 117, 110, 83, 0, 1, 0, 65}

  Z := S()
  //pesudo code from here
  i:= 0
  for field in Z {
    field = data[i:len(field)]
    i += len(field)
  }

期待:

  • f1 = [83,117,110,83]
  • f2 = [0,1]
  • f3 = [0,65]

我以前在 C/C++ 中做过这个,但我不知道如何在 Go 中做。我需要分配 function 是通用的,因为我将有几个不同的结构,其中一些可能不存在于stream。

理想情况下,我想传入初始化的结构,我的代码将遍历填充它们的结构字段。

利用二进制/编码 package 中的反射代码。

第 1 步:将字段声明为 arrays 而不是切片。

type S struct {
  F1 [4]byte
  F2 [2]byte
  F3 [2]byte
}

第 2 步:使用binary.Read将数据解码为结构

var s S
data := []byte{83, 117, 110, 83, 0, 1, 0, 65}
err := binary.Read(bytes.NewReader(data), binary.LittleEndian, &s)
if err != nil {
    log.Fatal(err)
}

第 3 步:完成!

fmt.Print(s) // prints {[83 117 110 83] [0 1] [0 65]}

https://go.dev/play/p/H-e8Lusw0RC

您可以使用reflect.Copy 像内置的copy一样,它将数据复制到目的地,直到它的长度。 确保您需要设置的字段已导出。

func main() {
    data := []byte{83, 117, 110, 83, 0, 1, 0, 65}

    z := S{
        F1: make([]byte, 4),
        F2: make([]byte, 2),
        F3: make([]byte, 2),
    }
    SetBytes(&z, data)
    fmt.Println(z) // {[83 117 110 83] [0 1] [0 65]}
}

func SetBytes(dst any, data []byte) {
    v := reflect.ValueOf(dst)
    if v.Kind() != reflect.Ptr {
        panic("dst must be addressable")
    }
    v = v.Elem()

    j := 0
    for i := 0; i < v.NumField(); i++ {
        field := v.Field(i)
        if field.Kind() != reflect.Slice {
            continue
        }
        j += reflect.Copy(v.Field(i), reflect.ValueOf(data[j:]))
    }
}

由于假定data始终为[]byte ,因此您可以直接对其进行细分。

或者,您可以使用reflect.Value#Slice

d := reflect.ValueOf(data)
// and later
j += reflect.Copy(v.Field(i), d.Slice(j, d.Len()))

游乐场: https://go.dev/play/p/o1MR1qrW5pL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM