为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕哥6287543 2023-08-07 15:28:39
我正在尝试创建一个函数,它从 Mongo 集合中获取所有文档并查询它们以声明的结构。为了实现这一点,我设置了类型接口函数的参数,以便它可以使用两个结构。这是我的代码:在包实体中:type Project struct {    Title string    Position string    ....}type Projects struct {    Projects []Project}在当前包中:var docs entities.Projectsvar 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(因此它甚至可能不起作用)。当我尝试将文档附加到文档界面时,程序就会中断。
查看完整描述

1 回答

?
白衣染霜花

TA贡献1796条经验 获得超10个赞

问题中的代码将结构传递docs给需要切片的函数。传递切片字段的地址而docs不是docs其本身。


该createQuery函数可以从切片本身确定切片元素类型。无需传递示例值。


var docs entities.Projects

createQuery(&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.Project

createQuery(&docs, collection)

for _, doc := range docs {

   fmt.Println(doc.Title)

}


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 97 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信