Контекст: я пытаюсь взять любой struct
и заполнить его случайными данными.
Моя большая проблема в данный момент заключается в том, что если struct
имеет поле, которое является срезом с типом указателя (ie. []*Foo
) я не могу понять, как создать данные для этой структуры с помощью отражения.
Вот как выглядит моя функция в настоящее время:
func randFill(in interface{}) interface{} {
t := reflect.TypeOf(in)
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
newStr := reflect.New(t).Elem()
for i := 0; i < t.NumField(); i++ {
newV := randFill(reflect.New(t.Field(i).Type).Interface())
newStr.Field(i).Set(reflect.ValueOf(newV))
}
return newStr.Interface()
case reflect.Slice:
num := rand.Intn(10)
slice := reflect.MakeSlice(v.Type(), num, num)
for j := 0; j < num; j++ {
newC := slice.Index(j)
if newC.Kind() == reflect.Ptr {
ncInt := reflect.New(newC.Type())
newC = ncInt.Elem()
}
gen := randFill(newC.Interface())
slice.Index(j).Set(reflect.ValueOf(gen))
}
return slice.Interface()
//
// ... there are other cases down here for handling primitives
//
}
return nil
}
Это прекрасно работает на слайсе без типов указателей, но вот пример некоторых структур, с которыми у него возникают проблемы:
type Parent struct {
Name string
Age int
Children []*Child
}
type Child struct {
Name string
Age int
}
Где, если я создал Parent{}
и передал его в randFill(Parent{})
, у него возникают проблемы при генерации значений для *Child
, потому что, когда он попадает в эту строку:
newC := slice.Index(j)
Значение newC
в этой точке при обработке среза []*Child
равно (*Child)(nil)
и это тип reflect.Value
.
newC := slice.Index(j)
fmt.Printf("%#v, %T", newC, newC) // Outputs: (*Child)(nil), reflect.Value
Есть что-то, чего мне не хватает в способности инициализировать тип указателя из reflect.Value
, или я создал неверный тип слайса, и это root моих проблем?