Reputation: 109
I have code and when I try this call console write undefined: insertContractData
. I try to change this code but get error on Invalid memory address or nil pointer dereference
I can't to understand how to do it right.
I think what I not right write struct I can't this compile still two days please what I do not so.
I use the official Mongo-go driver to connect to the pride of the language, so I can’t connect to the Plaza itself more precisely as an official document. If it’s all mine, it turned out to be connected. And individually, to connect each collection, it doesn’t work This code should generally start to work somehow, but the work doesn’t happen, or rather it works incorrectly, swears at the structure, so it’s rather swears at a method that is not named Here’s how to fix it, I don’t know, but I hope there are some solutions to this issue Here it thanks for the help.
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)
}
Upvotes: 1
Views: 239
Reputation: 417807
There are a handful of problems with your example.
First, context.WithTimeout()
returns you a context.Context
and a cancel
function which you're expected to call, preferably with defer
to make sure allocated resources are freed.
Next, NewMyClient()
is responsible to connect to the MongoDB server, but in your code you never call it. You should call it in your main()
.
Going forward, in main()
the insertContractData
identifier is undefined. You most likely want to register the mc.insertContractData
method as the handler (which is a method value btw).
You should never close the MongoDB connection, and certainly not at the end of your handler, and neither in your NewMyClient()
function. defer mc.mc.Disconnect(ctx)
lines are not only unneeded, they make your app disfunctional. mongo.Client
is designed to be long-lived. It has an internal connection pool, and it should be created just once, and reused from multiple goroutines. It should only be closed on app shutdown.
So your main()
function should look like this:
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()
could look like this:
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
}
And the handler:
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)
}
}
Now we can run this app.
We may test it with the following curl
command:
curl -d '{"number":"11","driver":"dr1","status":"s1"}' -X POST http://localhost:8081/insertContractData
And if we connect to the MongoDB database, and execute db.test.find()
, we'll see the following documents:
{ "_id" : ObjectId("5e123e6c1618bd4c80a2e13f"), "number" : "11", "driver" : "dr1", "auto" : "", "tariff" : "", "begindate" : "", "enddate" : "", "continues" : false, "moreInfo" : "", "status" : "s1" }
Upvotes: 4