Golang无法在MongoDB中创建文档。

huangapple go评论82阅读模式
英文:

Golang unable to create a document in MongoDB

问题

我正在尝试将一个文档插入到MongoDB中,但是尽管成功连接到Mongo,但我一直收到以下错误:

http: panic serving 172.27.0.8:40176: runtime error: invalid memory address or nil pointer dereference

我的main.go文件中,我正在初始化数据库连接,代码如下:

func main(){
   
      //连接到Mongo
      mongoClient,err:=connectToMongo()
      if err!=nil{
          log.Panic(err)
      }
      client=mongoClient
      
      //创建一个Mongo需要的上下文以便断开连接
      ctx,_:=context.WithTimeout(context.Background(), 15*time.Second)
      
      //关闭连接
      defer func ()  {
          if err =client.Disconnect(ctx); err!=nil{
              panic(err)
          }
      }() 

    muxRouter := mux.NewRouter().StrictSlash(true)

	//指定允许连接的来源
	c:=cors.New(cors.Options{ 
		AllowedOrigins: []string{"https://*", "http://*"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
		ExposedHeaders: []string{"Link"},
		AllowCredentials: true,
		MaxAge: 300,
})
	router := AddRoutes(muxRouter)
	handler := c.Handler(router)
    log.Println("Service stratring at o  port ",webPort)

    sterr := http.ListenAndServe(":9090", handler) //使用docker时取消注释此行
	if sterr != nil {
		log.Fatal("error starting http server :: ", err)
		return
	}

    log.Println("Service started at port ",webPort)
}

func connectToMongo()(*mongo.Client,error){
    mongoUsername := os.Getenv("MONGOUSERNAME")
    mongoPassword := os.Getenv("MONGOPASSWORD")
    //创建连接选项
    clientOptions:=options.Client().ApplyURI(mongoURL)
    clientOptions.SetAuth(options.Credential{
        Username: mongoUsername,
        Password: mongoPassword,
    })

    //连接
    c,err:=mongo.Connect(context.TODO(),clientOptions)
    if err!=nil{
        log.Println("Error connecting to mongo",err)
        return nil,err
    }
    log.Println("Connected to mongo")
    return c,nil
}

在一个单独的models.go文件中,我尝试将数据插入到数据库中,代码如下:

var client *mongo.Client
func  Insert(entry LogEntry)error{
	log.Printf("Attempting to insert %s", entry)
	log.Printf("client s  %s", client)
	//db:=client.Database("logs")
	//log.Printf("database  is  %s", db)
	
   collection:=client.Database("logs").Collection("logsCollection")
	log.Printf("collection is  %s", collection)

    _,err :=collection.InsertOne(context.TODO(), LogEntry{
        Name: entry.Name,
        Data: entry.Data,
        CreatedAt: time.Now(),
        UpdatedAt: time.Now(),
    })
    if err!=nil{
        log.Println("Error inserting new record into logs collection",err)
        return err
    }
	log.Println("insert successful")
    return nil
}

有人能发现我做错了什么吗?

英文:

I'm trying to insert a document into mongoDB but I keep getting the following error despite successfully managing to connect to mongo:

http: panic serving 172.27.0.8:40176: runtime error: invalid memory address or nil pointer dereference

My main.go where I'm initializing a database connection looks like this

func main(){
   
      //Connect to mongo
      mongoClient,err:=connectToMongo()
      if err!=nil{
          log.Panic(err)
      }
      client=mongoClient
  
      //Create a context that mongo needs in order to disconnect
      ctx,_:=context.WithTimeout(context.Background(), 15*time.Second)
     // ctx,cancel:=context.WithTimeout(context.Background(), 15*time.Second)
      //defer cancel()
      
  
      //close connection
      defer func ()  {
          if err =client.Disconnect(ctx); err!=nil{
              panic(err)
          }
      }() 

    muxRouter := mux.NewRouter().StrictSlash(true)

	//specify who's allowed to connect
	c:=cors.New(cors.Options{ 
		AllowedOrigins: []string{"https://*", "http://*"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
		ExposedHeaders: []string{"Link"},
		AllowCredentials: true,
		MaxAge: 300,
})
	router := AddRoutes(muxRouter)
	handler := c.Handler(router)
    log.Println("Service stratring at o  port ",webPort)

    sterr := http.ListenAndServe(":9090", handler) //Uncomment this line when using docker
	if sterr != nil {
		log.Fatal("error starting http server :: ", err)
		return
	}

    log.Println("Service started at port ",webPort)


    
  

}

func connectToMongo()(*mongo.Client,error){
    mongoUsername := os.Getenv("MONGOUSERNAME")
    mongoPassword := os.Getenv("MONGOPASSWORD")
    //create connection options
    clientOptions:=options.Client().ApplyURI(mongoURL)
    clientOptions.SetAuth(options.Credential{
        Username: mongoUsername,
        Password: mongoPassword,
    })

    //connect
    c,err:=mongo.Connect(context.TODO(),clientOptions)
    if err!=nil{
        log.Println("Error connecting to mongo",err)
        return nil,err
    }
    log.Println("Connected to mongo")
    return c,nil
}

In a separate file models.go is where I'm attempting to insert data into the database as follows:

var client *mongo.Client
func  Insert(entry LogEntry)error{
	log.Printf("Attempting to insert %s", entry)
	log.Printf("client s  %s", client)
	//db:=client.Database("logs")
	//log.Printf("database  is  %s", db)
	
   collection:=client.Database("logs").Collection("logsCollection")
	log.Printf("collection is  %s", collection)

    _,err :=collection.InsertOne(context.TODO(), LogEntry{
        Name: entry.Name,
        Data: entry.Data,
        CreatedAt: time.Now(),
        UpdatedAt: time.Now(),
    })
    if err!=nil{
        log.Println("Error inserting new record into logs collection",err)
        return err
    }
	log.Println("insert successful")
    return nil
}

Can anyone spot what I'm doing wrong?

答案1

得分: 1

由于错误是通用的(例如,没有提供错误的行号),我将分享一个可行的解决方案,也许可以帮助你找出问题所在。让我先分享代码。

main.go 文件

package main

import (
	"context"
	"fmt"
	"time"

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

type LogEntry struct {
	Name      string
	Data      string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
	defer cancel()

	clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
	mongoClient, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		panic(err)
	}
	defer mongoClient.Disconnect(ctx)

	demoDb := mongoClient.Database("demodb")
	myCollection := demoDb.Collection("myCollection")

	// delete documents
	if _, err := myCollection.DeleteMany(ctx, bson.M{}); err != nil {
		panic(err)
	}

	// insert data
	insertRes, err := myCollection.InsertOne(ctx, LogEntry{
		Name:      "lorem ipsum",
		Data:      "lorem ipsum",
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(insertRes.InsertedID)

	// query data
	cursor, err := myCollection.Find(ctx, bson.M{})
	if err != nil {
		panic(err)
	}
	var logEntries []bson.M
	if err = cursor.All(ctx, &logEntries); err != nil {
		panic(err)
	}
	for _, v := range logEntries {
		fmt.Println(v)
	}
}

为了演示的目的,我将所有逻辑放在了一个文件中。在这个文件中,我完成了以下步骤:

  1. 设置 MongoDB 连接。
  2. 连接到数据库和其中的一个集合。
  3. 删除已经存在的所有文档(只是为了更清晰)。
  4. myCollection 集合中插入一个新的 LogEntry 实例。
  5. 检索 myCollection 集合中的所有条目。

最后要提到的是我用于运行容器的 Docker 命令:

docker run -d -p 27017:27017 --name mymongo -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root mongo:latest

如果你按照我的解决方案进行操作,应该能够成功插入一个文档。如果不是这种情况,请告诉我,我会尽力帮助你!

英文:

As the error is generic (e.g. the line number of the error is not provided) I'm gonna share a working solution that maybe can help you in figuring out what's wrong. Let me share the code first.

main.go file

package main

import (
	"context"
	"fmt"
	"time"

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

type LogEntry struct {
	Name      string
	Data      string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
	defer cancel()

	clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
	mongoClient, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		panic(err)
	}
	defer mongoClient.Disconnect(ctx)

	demoDb := mongoClient.Database("demodb")
	myCollection := demoDb.Collection("myCollection")

	// delete documents
	if _, err := myCollection.DeleteMany(ctx, bson.M{}); err != nil {
		panic(err)
	}

	// insert data
	insertRes, err := myCollection.InsertOne(ctx, LogEntry{
		Name:      "lorem ipsum",
		Data:      "lorem ipsum",
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(insertRes.InsertedID)

	// query data
	cursor, err := myCollection.Find(ctx, bson.M{})
	if err != nil {
		panic(err)
	}
	var logEntries []bson.M
	if err = cursor.All(ctx, &logEntries); err != nil {
		panic(err)
	}
	for _, v := range logEntries {
		fmt.Println(v)
	}
}

For the sake of the demo, I put all of the logic inside a single file. Within this file, I did the following steps:

  1. Set up a MongoDB connection.
  2. Connect to a database and to a collection within that database.
  3. Delete all of the documents that were already there (just to be clearer).
  4. Insert a new LogEntry instance in the myCollection collection.
  5. Retrieve all of the entries in the myCollection collection.

Last thing to mention is the Docker command I used to run my container:

docker run -d -p 27017:27017 --name mymongo -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root mongo:latest

If you stick to my solution, you should be able to insert a document without any issue. If not the case, just let me know and I'll try to help you!

huangapple
  • 本文由 发表于 2023年3月22日 04:21:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75806007.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定