mercredi 8 avril 2020

How to construct slice of structs dynamically using reflection in golang?

I was trying to construct slice of Book structs with pointers but i was unable to get it work with reflection in golang.

[]*Book slice of Book struct pointers , please note that scanResults method might receive any type of slice and not only Book struct. So am looking to build a slice at runtime dynamically

Can you please let me know what i was getting wrong in the below code snippet ? Thank you.

type Book struct {
    Id    int
    Title string
    Price float32
}

func main() {
    var dest []*Book
    scanResults(&dest)
}

func scanResults(dest interface{}) error{
   resultsFromExternalSource = []interface{}{10 , "user-name" , float32(22)}

    value := reflect.ValueOf(dest)
    if value.Kind() != reflect.Ptr {
        return errors.New("must pass a pointer, not a value, to scan results into struct destination")
    }

    sliceElement := reflect.TypeOf(dest).Elem()
    if sliceElement.Kind() != reflect.Slice {
        return fmt.Errorf("expected %s but got %s", reflect.Slice, sliceElement.Kind())
    }

    structPtr := sliceElement.Elem()
    if structPtr.Kind() != reflect.Ptr {
        return fmt.Errorf("expected %s but got %s", reflect.Ptr, structPtr.Kind())
    }

    structElemType := reflect.TypeOf(structPtr).Elem()
    if structElemType.Kind() != reflect.Struct {
        return fmt.Errorf("expected %s but got %s", reflect.Struct, structElemType.Kind())
    }

    structNumberOfFields := structElemType.NumField()
    for i, result := range resultsFromExternalSource {
        values := make([]interface{}, structNumberOfFields)

            structRecordInterface := reflect.New(structElemType).Elem().Interface() // create a new struct
            structRecordType := reflect.TypeOf(structRecordInterface)
            structRecordValue := reflect.ValueOf(structRecordType)

                if structRecordValue.Field(i).CanSet() {
                    structRecordValue.Field(i).Set(reflect.ValueOf(config.FieldValueToValue(fieldValue)))
                } else {
                    varName := structRecordType.Field(i).Name
                    varType := structRecordType.Field(i).Type
                    return fmt.Errorf("cannot scan results into passed struct destination as the struct field %v with %v type is not settable", varName, varType)
                }
            }

        }

    }
}




Aucun commentaire:

Enregistrer un commentaire