一尘不染

Reflect认为struct值也是ptr吗?

go

我有一个像这个演示这样的数据结构。如您所见,foo有一个嵌入式指针指向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()被认为是a
reflect.Struct,但是如果我尝试通过使用将其视为结构.FieldByName("S"),它会慌张,因为它认为v是a ptr

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

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

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

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


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

panic: runtime error: invalid memory address or nil pointer dereference


阅读 260

收藏
2020-07-02

共1个答案

一尘不染

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

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

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

您可以将更改为var f foo来修复这两个错误f := foo{&bar{}}

2020-07-02