反映认为结构值也是一个ptr



我有一个像这个演示这样的数据结构。如您所见,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()被认为是一个reflect.Struct,但是如果我试图通过使用.FieldByName("S")来把它当作一个结构体,它会惊慌失措,因为它认为v是一个ptr

因此,如果我试图通过打电话.Elem()来将其视为ptr,它会惊慌失措,因为它认为v是一个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

我们需要意识到的第一件事是 行var f foo等价于 f := foo{} .这会将内部字段bar(类型为 *bar)初始化为其零值...零。嵌入类型和反射的行为似乎是它将嵌入类型的字段视为类型本身的字段。因此,当您请求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{}} 来修复这两个错误。

我收到此错误" 恐慌:反射:反射的调用。Value.Elem on struct Value" bcz 的这一行"反映。ValueOf(参数名称)。Elem()"

1.当我在反射中使用Elem()时,这意味着valueOf()中的参数名称应该是指向结构的指针

func Search(flight interface{}, key string) string {
  val := reflect.ValueOf(flight).Elem()
  for i := 0; i < val.NumField(); i++ {
    valueField := val.Field(i)
    typeField := val.Type().Field(i)
    if key == strings.ToLower(typeField.Name) {
      return valueField.Interface().(string)
    }
  }
  return ""
}

现在在调用搜索功能时,我的调用应该是这样的!结果 := 搜索(&航班,键)