Как передать массив struct как интерфейс по ссылке - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь прочитать все документы в данной коллекции Firestore и вернуть документы в виде массива struct. Журнал внутри функции выводит данные в виде документов Firestore, но массив struct вне функции всегда является пустым массивом.

Функция для чтения всех документов в коллекции.

func (fc *FirebaseClient) ReadCollection(collectionPath string, objects interface{}) error {
    ctx := context.Background()
    opt := option.WithCredentialsJSON([]byte(os.Getenv("FIREBASE_CREDENTIALS")))
    client, err := firestore.NewClient(ctx, os.Getenv("FIREBASE_PROJECT_ID"), opt)
    if err != nil {
        return err
    }
    defer client.Close()

    collectionRef := client.Collection(collectionPath)
    docs, err := collectionRef.DocumentRefs(ctx).GetAll()
    if err != nil {
        return err
    }
    log.Printf("Total documents: %i", len(docs))
    objs := make([]interface{}, len(docs))
    for i, doc := range docs {
        docsnap, err := doc.Get(ctx)
        if err != nil {
            return err
        }

        if err := docsnap.DataTo(&objs[i]); err != nil {
            return err
        }
        log.Printf("obj: %v", objs[i])

    }

    objects = objs
    log.Printf("objects: %v", objects)
    return nil
}

Код для вызова функции

    var ss []SomeStruct

    fc := new(insightech.FirebaseClient)
    if err := fc.ReadCollection("mycollection", ss); err != nil {
        return
    }

ss - это всегда пустой массив.

Причина, по которой я не хочу указывать тип структуры, состоит в том, чтобы сделать ReadCollectionфункция универсальная, поэтому я могу вызывать ее для чтения различных коллекций.

Код не вызывает никаких ошибок, но в результате получается пустой массив, хотя интерфейс objects определенно является массивом с элементами.

1 Ответ

1 голос
/ 06 ноября 2019

Благодаря @mkopriva работает следующий код:

func (fc *FirebaseClient) ReadCollection(collectionPath string, objects interface{}) error {
    ctx := context.Background()
    opt := option.WithCredentialsJSON([]byte(os.Getenv("FIREBASE_CREDENTIALS")))
    client, err := firestore.NewClient(ctx, os.Getenv("FIREBASE_PROJECT_ID"), opt)
    if err != nil {
        return err
    }
    defer client.Close()

    collectionRef := client.Collection(collectionPath)
    docs, err := collectionRef.DocumentRefs(ctx).GetAll()
    if err != nil {
        return err
    }
    log.Printf("Total documents: %i", len(docs))

    dest := reflect.ValueOf(objects).Elem()


    log.Printf("dest: %v", dest)
    for _, doc := range docs {
        docsnap, err := doc.Get(ctx)
        if err != nil {
            return err
        }

        obj := reflect.New(dest.Type().Elem())

        if err := docsnap.DataTo(obj.Interface()); err != nil {
            return err
        }
        log.Printf("obj: %v", obj)
        dest = reflect.Append(dest, obj.Elem())


    }

    reflect.ValueOf(objects).Elem().Set(dest)
    log.Printf("objects: %v", dest)
    return nil
}
    var ss []SomeStruct

    fc := new(insightech.FirebaseClient)
    if err := fc.ReadCollection("mycollection", &ss); err != nil {
        return
    }
...