猿问

使用“reflect”将数据附加到指向已定义结构的接口

我正在尝试创建一个函数,它从 Mongo 集合中获取所有文档并查询它们以声明的结构。为了实现这一点,我设置了类型接口函数的参数,以便它可以使用两个结构。这是我的代码:


在包实体中:


type Project struct {

    Title string

    Position string

    ....

}


type Projects struct {

    Projects []Project

}

在当前包中:


var docs entities.Projects

var doc entities.Project


//doc represents a document from Mongo Collection 

//docs represents an array of documents, each element is a document

//collection has type *mongo.Collection and points to the desired collection on MongoDB.

createQuery(&doc, &docs, collection)


func createQuery(doc interface{}, docs interface{}, c *mongo.Collection) {

    documents := reflect.ValueOf(docs).Elem()

    document := reflect.ValueOf(doc)


    cur, err := c.Find(context.Background(), bson.D{{}})


    if err != nil {

        log.Fatal(err)

    }

    for cur.Next(context.Background()) {

        err = cur.Decode(document.Interface())

        if err != nil {

            log.Fatal(err)

        }

        //Error is thrown here

        documents.Set(reflect.Append(documents, document))

        fmt.Println(doc)

    }

    if err := cur.Err(); err != nil {

        log.Fatal(err)

    }


    if err != nil {

        fmt.Printf("oh shit this is the error %s \n", err)

    }

    cur.Close(context.Background())


    fmt.Printf("documents: %+v\n", documents.Interface())

    fmt.Printf("document: %+v\n", document.CanSet())

}



---ERROR OUTPUT---

panic: reflect: call of reflect.Append on struct Value

我能够使用文档变量将数据设置为 doc,尽管在执行 document.CanSet() 时为 false(因此它甚至可能不起作用)。当我尝试将文档附加到文档界面时,程序就会中断。


慕哥6287543
浏览 98回答 1
1回答

白衣染霜花

问题中的代码将结构传递docs给需要切片的函数。传递切片字段的地址而docs不是docs其本身。该createQuery函数可以从切片本身确定切片元素类型。无需传递示例值。var docs entities.ProjectscreateQuery(&docs.Projects, collection)for _, doc := range docs.Projects {   fmt.Println(doc.Title)}调用cur.Decode需要一个指向未初始化值的指针。使用reflect.New 来创建该值。func createQuery(docs interface{}, c *mongo.Collection) {    docsv := reflect.ValueOf(docs).Elem()    doct := docsv.Type().Elem()    cur, err := c.Find(context.Background(), bson.D{{}})    if err != nil {        log.Fatal(err)    }    for cur.Next(context.Background()) {        docpv := reflect.New(doct)        err = cur.Decode(docpv.Interface())        if err != nil {            log.Fatal(err)        }        docsv.Set(reflect.Append(docsv, docpv.Elem()))    }    if err := cur.Err(); err != nil {        log.Fatal(err)    }    cur.Close(context.Background())}顺便说一句,entities.Projects如果该结构类型只有一个字段,则不需要该结构类型。改用[]Project:var docs []entities.ProjectcreateQuery(&docs, collection)for _, doc := range docs {   fmt.Println(doc.Title)}
随时随地看视频慕课网APP

相关分类

Go
我要回答