【问题标题】:Insert MongoDB document from handler从处理程序插入 MongoDB 文档
【发布时间】:2020-04-23 11:24:35
【问题描述】:

我有代码,当我尝试这个调用控制台时,写undefined: insertContractData。我尝试更改此代码,但在Invalid memory address or nil pointer dereference 上出现错误我无法理解如何正确操作。

我觉得我写的结构不对 我还不能编译这两天请我不这样做。

我使用官方的 Mongo-go 驱动连接到骄傲的语言,所以我不能更准确地连接到 Plaza 本身作为官方文档。如果都是我的,结果证明是有联系的。并且单独地,连接每个集合,它不起作用这个代码通常应该以某种方式开始工作,但是工作没有发生,或者更确切地说它工作不正确,对结构发誓,所以它对一个方法发誓未命名这里是如何解决它,我不知道,但我希望有一些解决这个问题的方法在这里感谢您的帮助。

package main

import (
    "context"
    "encoding/json"
    "log"
    "net/http"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Data struct {
    Number    string `json:"number"`
    Driver    string `json:"driver"`
    Auto      string `json:"auto"`
    Tariff    string `json:"tariff"`
    Begindate string `json:"begindate"`
    Enddate   string `json:"enddate"`
    Continues bool   `json:"continues"`
    MoreInfo  string `json:"moreInfo"`
    Status    string `json:"status"`
}

type MyClient struct {
    mc *mongo.Client
    db *mongo.Database
}

func setupResponse(w http.ResponseWriter, req *http.Request) {
    (w).Header().Set("Access-Control-Allow-Origin", "*")
    (w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    (w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

func NewMyClient(url, db string) (mc *MyClient, err error) {
    defer func() {
        if err != nil {
            mc = nil
        }
    }()
    mc = &MyClient{}
    if mc.mc, err = mongo.NewClient(options.Client().ApplyURI(url)); err != nil {
        return
    }
    ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
    err = mc.mc.Connect(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer mc.mc.Disconnect(ctx)
    mc.db = mc.mc.Database(db)
    return
}

func (mc *MyClient) insertContractData(w http.ResponseWriter, r *http.Request) {
    setupResponse(w, r)
    var err error
    var data Data
    err = json.NewDecoder(r.Body).Decode(&data)
    if err != nil {
        return
    }

    podcastsCollection := mc.db.Collection("test")
    ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
    defer mc.mc.Disconnect(ctx)
    _, err = podcastsCollection.InsertOne(ctx, bson.D{
        {"number", data.Number},
        {"driver", data.Driver},
        {"auto", data.Auto},
        {"tariff", data.Tariff},
        {"begindate", data.Begindate},
        {"enddate", data.Enddate},
        {"continues", data.Continues},
        {"moreInfo", data.MoreInfo},
        {"status", data.Status},
    })
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    var mc MyClient
    http.HandleFunc("/insertContractData", insertContractData)
    //http.HandleFunc("/selectContractData", selectContractData)
    http.ListenAndServe(":8081", nil)
}

【问题讨论】:

    标签: mongodb http go struct mongo-go


    【解决方案1】:

    您的示例存在一些问题。

    首先,context.WithTimeout() 会返回一个 context.Context 和一个 cancel 函数,您应该调用它们,最好使用 defer 以确保释放分配的资源。

    接下来,NewMyClient() 负责连接到 MongoDB 服务器,但在您的代码中您永远不会调用它。你应该在main() 中调用它。

    接下来,在main() 中,insertContractData 标识符未定义。您很可能希望将 mc.insertContractData 方法注册为处理程序(这是一个 method value 顺便说一句)。

    您永远不应该关闭 MongoDB 连接,当然也不应该在处理程序结束时关闭,也不要在 NewMyClient() 函数中关闭。 defer mc.mc.Disconnect(ctx) 行不仅不需要,它们还会使您的应用程序无法正常工作。 mongo.Client 被设计为长寿命。它有一个内部连接池,它应该只创建一次,并从多个 goroutine 中重用。它应该只在应用关闭时关闭。

    所以你的main() 函数应该是这样的:

    func main() {
        mc, err := NewMyClient("mongodb://localhost:27017", "someDB")
        if err != nil {
            panic(err)
        }
        http.HandleFunc("/insertContractData", mc.insertContractData)
        panic(http.ListenAndServe(":8081", nil))
    }
    

    NewMyClient() 可能如下所示:

    func NewMyClient(url, db string) (mc *MyClient, err error) {
        mc = &MyClient{}
        if mc.mc, err = mongo.NewClient(options.Client().ApplyURI(url)); err != nil {
            return
        }
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        err = mc.mc.Connect(ctx)
        if err != nil {
            log.Fatal(err)
        }
        mc.db = mc.mc.Database(db)
        return
    }
    

    还有处理程序:

    func (mc *MyClient) insertContractData(w http.ResponseWriter, r *http.Request) {
        setupResponse(w, r)
        var err error
        var data Data
        err = json.NewDecoder(r.Body).Decode(&data)
        if err != nil {
            fmt.Println(err)
            return
        }
    
        podcastsCollection := mc.db.Collection("test")
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        _, err = podcastsCollection.InsertOne(ctx, bson.D{
            {"number", data.Number},
            {"driver", data.Driver},
            {"auto", data.Auto},
            {"tariff", data.Tariff},
            {"begindate", data.Begindate},
            {"enddate", data.Enddate},
            {"continues", data.Continues},
            {"moreInfo", data.MoreInfo},
            {"status", data.Status},
        })
        if err != nil {
            log.Fatal(err)
        }
    }
    

    现在我们可以运行这个应用了。

    我们可以使用以下curl 命令对其进行测试:

    curl -d '{"number":"11","driver":"dr1","status":"s1"}' -X POST http://localhost:8081/insertContractData
    

    如果我们连接到 MongoDB 数据库,并执行db.test.find(),我们将看到以下文件:

    { "_id" : ObjectId("5e123e6c1618bd4c80a2e13f"), "number" : "11", "driver" : "dr1", "auto" : "", "tariff" : "", "begindate" : "", "enddate" : "", "continues" : false, "moreInfo" : "", "status" : "s1" }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-21
      • 2012-08-29
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      相关资源
      最近更新 更多