Проверьте, является ли базовый тип структурой с отражением - PullRequest
1 голос
/ 08 марта 2020

Учитывая эту структуру

type A struct {
  b *B
  c string
  d string
}

Я хочу проверить с помощью отражения, какие поля имеют структуру за типом указателя, поэтому, в частности, я хочу создать условие, которое будет истинным только при итерации по полю b. Из того, что я пытался использовать отражающую документацию, я всегда получаю invalid Value вид, который не позволяет мне go дальше, так как каждый последующий метод паникует.

package main

import (
    "fmt"
    "reflect"
)

type A struct {
  b *B
  c string
  d string
}

type B struct {
}

func main() {
        val := reflect.ValueOf(A{})
    for i := 0; i < val.Type().NumField(); i++ {
        if val.Field(i).Kind() == reflect.Ptr {
            fmt.Println(reflect.Indirect(val.Field(i)).Kind())
        }
        fmt.Println(val.Field(i).Kind())
    }
}

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

1 Ответ

1 голос
/ 08 марта 2020

Вы получаете недопустимое значение, поскольку поле указателя val.b равно nil, и вы не можете разыменовать указатель nil. Если вы хотите, чтобы ваш код работал, вы должны инициализировать его с действительным указателем:

val := reflect.ValueOf(A{b: &B{}})

С этим изменением он работает и выводит данные (попробуйте на Go Playground ) :

struct
ptr
string

Если вы хотите, чтобы он работал без инициализации указателя, вам придется работать с типами , а не с значениями :

val := reflect.ValueOf(A{})
t := val.Type()
for i := 0; i < t.NumField(); i++ {
    if ft := t.Field(i).Type; ft.Kind() == reflect.Ptr {
        fmt.Println(ft.Elem().Kind())
    }
    fmt.Println(t.Field(i).Type.Kind())
}

Это выводит то же самое, попробуйте это на Go Детская площадка .

...