从处理程序插入 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" }
我有代码,当我尝试这个调用控制台时写 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" }