【问题标题】:Go Reflect Array去反射阵列
【发布时间】:2021-01-29 07:40:30
【问题描述】:

结构如下:

type Auth_msg struct {
    Msg_class       [2]byte
    Msg_content_pty [2]byte

我刚开始在 Go 中使用 Reflect,我遇到了这个问题:

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

当我运行 val.Field(i).Bytes() 时会发生这种情况,但是当我尝试打印它时:fmt.PrintLn(val.Field(i)),它会打印出正确的数组。

我只是想知道,如何在数组或切片中检索 Msg_class?

【问题讨论】:

  • val.Field(i).Index(j).Uint()
  • 遍历数组元素是否强制?
  • "compulsory" 不,你总是可以做丑陋的不安全的把戏。鉴于我们在这里讨论了 2 个(换句话说:两个)元素,没有理由不一个接一个地访问这两个数组元素。
  • 不,没有。数组在 Go 中很少见,并且包 reflect 对数组的支持不如对切片(尤其是字节切片)的支持。请注意,您始终可以执行 val.Field(i).Interface().([2]byte)。这是否更清晰、更安全、更快是您必须决定的事情。
  • 非常感谢您的详细阐述。我明白你的意思。

标签: go reflect


【解决方案1】:

在 Go 中,arrayslice 是有区别的。 Value.Bytes() 明确仅适用于字节切片 (link to docs)。
注意:我不知道为什么它不处理字节数组;它可能是这样写的,它使reflect.Bytes() 的实现更简单。无论如何:切片绝对是 Go 中的常见用例,并且很容易将数组转换为切片:


您可以使用[:] 创建一个指向arrayslice

    v := reflect.ValueOf(msg.Msg_class)
    fmt.Println("kind :", v.Kind()) // prints 'array'
    // fmt.Printf("bytes : % x\n", v.Bytes())  // panics

    v = reflect.ValueOf(msg.Msg_class[:])
    fmt.Println("kind :", v.Kind())        // prints 'slice'
    fmt.Printf("bytes : % x\n", v.Bytes()) // works

https://play.golang.org/p/sKcGaru4rOq


要使用反射将数组转换为切片,您可以在 reflect.Value 上调用 .Slice()

the doc 中提到的一个约束是数组值必须是可寻址
我还没有整理出所有细节,但确保反射值可寻址的一种方法是在 指针 上调用 reflect.ValueOf(),然后在该指针值上调用 .Elem()

var arr [2]byte
arr[0] = 'g'
arr[1] = 'o'

// take ValueOf a *pointer* to your array, and let reflect dereference it :
v := reflect.ValueOf(&arr).Elem()
// this sets the "canAddr" flag on this value
fmt.Println("arr value - CanAddr() :", v.CanAddr()) // prints 'true'
slice := v.Slice(0, v.Len())
fmt.Printf("arr bytes : % x\n", slice.Bytes()) // prints '67 6f'

// for a field inside a struct : take a pointer to the struct
var msg Auth_msg
msg.Msg_class[0] = 'a'
msg.Msg_class[1] = 'z'

v = reflect.ValueOf(&msg).Elem()
fmt.Println("msg value - CanAddr() :", v.CanAddr()) // prints 'true'

// now reflect accepts to call ".Slice()" on one of its fields :
field := v.FieldByName("Msg_class")
slice = field.Slice(0, field.Len())
fmt.Printf("msg.Msg_class bytes : % x\n", slice.Bytes()) // prints '61 7a'

https://play.golang.org/p/SqM7yxl2D96

【讨论】:

  • 我看到了slicearray 的区别。情况是我正在遍历msg 中的元素。所以我必须写val := reflect.TypeOf(msg),所以这里的i指的是像Msg_class这样的msg中的元素。如果Msg_class 是一个切片,则表达式显然是val.Field(i).Bytes。但是现在它是一个数组,所以我想要一个val.Field(i).Bytes-like-expression
猜你喜欢
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多