首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从处理程序插入MongoDB文档

从处理程序插入MongoDB文档
EN

Stack Overflow用户
提问于 2020-01-06 03:07:16
回答 1查看 80关注 0票数 1

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

我想我不对写struct的,我不能这个编译,还是两天,请不要这样做。

我使用官方的Mongo-go驱动程序来连接语言的骄傲,所以我不能更准确地连接到Plaza本身作为官方文件。如果都是我的,那就是有关联的。单独地,连接每个集合,它不工作,这个代码通常应该开始工作,但是工作没有发生,或者更确切地说,它工作不正确,在结构上发誓,所以它相当于一个没有命名的方法,这里是如何修复它,我不知道,但我希望这里有一些解决这个问题的解决方案,谢谢你的帮助。

代码语言:javascript
复制
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)
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-06 03:50:25

你的例子有几个问题。

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

接下来,NewMyClient()负责连接到MongoDB服务器,但在您的代码中从未调用过它。您应该在main()中调用它。

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

您永远不应该关闭MongoDB连接,当然不应该在处理程序结束时关闭,也不应该在NewMyClient()函数中关闭。defer mc.mc.Disconnect(ctx)行不仅是不必要的,它们还会使您的应用程序功能失调。mongo.Client的设计是长寿的。它有一个内部连接池,应该只创建一次,并在多个goroutine中重用。它应该只在应用程序关闭时关闭。

因此,您的main()函数应该如下所示:

代码语言:javascript
复制
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()可能如下所示:

代码语言:javascript
复制
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
}

和操控者:

代码语言:javascript
复制
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命令对其进行测试:

代码语言:javascript
复制
curl -d '{"number":"11","driver":"dr1","status":"s1"}' -X POST http://localhost:8081/insertContractData

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

代码语言:javascript
复制
{ "_id" : ObjectId("5e123e6c1618bd4c80a2e13f"), "number" : "11", "driver" : "dr1", "auto" : "", "tariff" : "", "begindate" : "", "enddate" : "", "continues" : false, "moreInfo" : "", "status" : "s1" }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59603268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档