Reflect认为struct值也是ptr吗? [英] Reflect thinks struct Value is also a ptr?

查看:65
本文介绍了Reflect认为struct值也是ptr吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似此演示的数据结构.如您所见, foo 具有指向 bar 的嵌入式指针:

I have a data structure like this demo. As you can see, foo has an embedded pointer to bar:

type foo struct {
    *bar
}

type bar struct {
    S []byte
}

我正在像这样使用 reflect 包:

func test(x interface{}) {

    var v = reflect.ValueOf(x)

    if v.Kind() == reflect.Struct {
        fmt.Println("was a struct")

    // panic: reflect: call of reflect.Value.Elem on struct Value
    //  v = v.Elem()

    // panic: reflect: call of reflect.Value.Field on ptr Value
        v = v.FieldByName("S")
    }
}

func main() {
    var f foo
    test(f)
    fmt.Println(string(f.S))
}

因此, v.Kind()被识别为 reflect.Struct ,但是如果我尝试通过使用 .FieldByName("S),因为它认为 v ptr .

So v.Kind() is recognized as a reflect.Struct, but if I try to treat it like a struct by using .FieldByName("S"), it panics because it thinks v is a ptr.

因此,如果我尝试通过调用 .Elem()来将其视为 ptr ,它会感到恐慌,因为它认为 v 是一个 struct .

So then if I try to treat it like a ptr by calling .Elem(), it panics because it thinks v is a struct.

我已经尝试过 reflect.Indirect()以及其他一些事情,但是我不知道如何获取嵌入式指针的字段.

I've tried reflect.Indirect(), as well as a few other things, but I can't figure out how to get the field of an embedded pointer.

是否有一种方法可以从嵌入的指向结构的指针中获取 reflect.Value 表示形式?

Is there a way to get the reflect.Value representation from an embedded pointer to a struct?

演示: : http://play.golang.org/p/n0eea6XW3I

也尝试了 v = v.FieldByName("bar"),但得到了:

紧急:运行时错误:无效的内存地址或nil指针取消引用

推荐答案

我们需要意识到的第一件事是 var f foo 行等效于 f:= foo {}.这会将内部字段 bar (* bar类型)初始化为其零值... nil.嵌入类型和反映的行为似乎是将嵌入类型的字段视为类型本身的字段.因此,当您请求 v.FieldByName("S")时,它会尝试在f的成员bar中找到该字段,该字段为nil.

The first thing we need to realize is that the line var f foo is equivalent to f := foo{}. This initializes the internal field bar (of type *bar) to its zero value... nil. The behavior of embedded types and reflect seems to be that it treats the embedded type's fields as fields of the type itself. So when you request v.FieldByName("S") it's trying to find that field in f's member, bar, which is nil.

您正在尝试执行此(* f.bar).S .(在Go语言中,不需要显式指针取消引用,但这是我的意思).现在的问题是:如果更改为 v.FieldByName("bar"),为什么会出现错误?相同的原因.

You're trying to do this (*f.bar).S. (In Go the explicit pointer dereference isn't needed, but it makes my point). Now the question is: if you change is to v.FieldByName("bar") why does it give an error? Same reason.

仔细查看堆栈跟踪, FieldByName 行不再崩溃,崩溃的行是 fmt.Println(string(f.S)).同样,从语义上讲,您正在执行(* f.bar).S .但是成员"bar"为nil,因此实际上是在进行nil指针取消引用.

Look closely at the stack trace, the FieldByName line no longer crashes, the line that crashes is fmt.Println(string(f.S)). Again, semantically you're doing (*f.bar).S. But the member "bar" is nil, so you are, in fact, doing a nil pointer dereference.

您可以通过将 var f foo 更改为 f:= foo {& bar {}} 来解决这两个错误.

You can fix both errors by changing var f foo to f := foo{&bar{}}.

这篇关于Reflect认为struct值也是ptr吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆