【发布时间】:2020-02-18 17:57:49
【问题描述】:
我正在尝试为复杂数据类型制作通用调试打印机,因为%v 倾向于只打印指针值而不是它们指向的内容。在我必须处理包含 reflect.Value 字段的结构之前,我已经让它与所有东西一起工作。
以下演示代码运行无误:(https://play.golang.org/p/qvdRKc40R8k)
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
i int
R reflect.Value
}
func printContents(value interface{}) {
// Omitted: check if value is actually a struct
rv := reflect.ValueOf(value)
for i := 0; i < rv.NumField(); i++ {
fmt.Printf("%v: ", rv.Type().Field(i).Name)
field := rv.Field(i)
switch field.Kind() {
case reflect.Int:
fmt.Printf("%v", field.Int())
case reflect.Struct:
// Omitted: check if field is actually a reflect.Value to an int
fmt.Printf("reflect.Value(%v)", field.Interface().(reflect.Value).Int())
}
fmt.Printf("\n")
}
}
func main() {
printContents(MyStruct{123, reflect.ValueOf(456)})
}
打印出来:
i: 123
R: reflect.Value(456)
但是,如果我将 MyStruct 的 R 字段名称更改为 r,则会失败:
panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
当然,失败是正确的,因为否则这将是一种将未出口的田地进入适当的戈兰的方法,这是一个禁忌。
但这让我陷入了困境:如何在不使用 Interface() 的情况下访问未导出的 reflect.Value 所指的任何内容,以便我可以浏览其内容并打印?我浏览了反射文档,没有发现任何看起来有用的东西......
【问题讨论】:
-
您是否查看过此类功能的许多现有实现中的任何一个,例如github.com/davecgh/go-spew?
-
您可以这样做:play.golang.org/p/MWnjy1iIrJQ 请注意,我传递了一个指向原始结构的指针,以便这些字段是可寻址的。然而,更重要的是,要完成这项工作,您需要使用
unsafe包,如果没有适当考虑,不应使用它。
标签: go reflection