从处理程序插入 MongoDB 个文档

Insert MongoDB document from handler

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

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

我使用的是官方的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)
}

您的示例存在一些问题。

首先,context.WithTimeout() returns you a context.Context 和一个您需要调用的 cancel 函数,最好使用 defer 以确保释放分配的资源。

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

中调用它

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

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

所以您的 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" }