【问题标题】:the Insert operation must have a Deployment set before Execute can be called在调用 Execute 之前,插入操作必须有一个部署集
【发布时间】:2020-03-30 10:46:26
【问题描述】:

我有一个运行 MongoDB 的 AWS 实例。我正在尝试做一个小的 db 操作,当下面包含的文件被写入单个 go 文件时,它似乎可以工作。当我尝试拆分它时,出现以下错误

在调用 Execute 之前,插入操作必须有一个部署集

拆分文件如下所示

connect.go

package db

import (
	"context"
	"fmt"
	"log"

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

var Client1 mongo.Client

func Connect() {
	// Set client options
	clientOptions := options.Client().ApplyURI("remote_url")

	// Connect to MongoDB
	Client1, err := mongo.Connect(context.TODO(), clientOptions)

	if err != nil {
		log.Fatal(err)
	}

	// Check the connection
	err = Client1.Ping(context.TODO(), nil)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Connected to MongoDB!")
}

func main() {
	fmt.Println("Connection to MongoDB done.")
}

main.go

package main

import (
	"context"
	"fmt"
	"log"

	"db"

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

// You will be using this Trainer type later in the program
type Trainer struct {
	Name string
	Age  int
	City string
}

func main() {

	db.Connect()
	collection := db.Client1.Database("test2").Collection("trainers")
	_ = collection

	fmt.Println("Created collection", _)

	ash := Trainer{"Ash", 10, "Pallet Town"}
	// misty := Trainer{"Misty", 10, "Cerulean City"}
	// brock := Trainer{"Brock", 15, "Pewter City"}

	insertResult, err := collection.InsertOne(context.TODO(), ash)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Inserted a single document: ", insertResult)

	err = db.Client1.Disconnect(context.TODO())

	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Connection to MongoDB closed.")
}

它们被放置在以下结构中

/src -> main.go
/src -> /db/connect.go

【问题讨论】:

  • 你在使用 go 模块吗?您如何编译/运行您的应用程序?
  • 不,我没有使用 go 模块。我使用命令编译它:go run main.go
  • @SidharthV,我希望你解决了你的问题。如果没有阅读 this article 。不过,如果你不明白,请告诉我,我会写一个详细的答案。

标签: mongodb go amazon-ec2


【解决方案1】:

我相信您的问题是由 variable shadowing (wiki) 引起的,并且您正在初始化一个局部变量而不是全局 mongo.Client 对象,因此您得到的是 throwing the error

它发生在您的 connect.go 文件中,您在该文件中定义了两个具有相同名称的不同 Client1 变量:

  1. 一个在全球范围内
  2. Connect() 中的另一个在调用 mongo.Connect() 时被声明+初始化

    var Client1 mongo.Client // Client1 at global scope
    
    func Connect() {
        // Set client options
        clientOptions := options.Client().ApplyURI("remote_url")
    
        // Connect to MongoDB
        Client1, err := mongo.Connect(context.TODO(), clientOptions) // Client1 at local scope within Connect()
    

这导致全局范围的那个永远不会被初始化,所以 main.go 在尝试使用它时会崩溃,因为它是 nil。

有几种方法可以解决这个问题,例如在本地范围内为变量使用不同的名称并将客户端分配给全局范围:

    var Client1 mongo.Client

    func Connect() {
        // Set client options
        clientOptions := options.Client().ApplyURI("remote_url")

        // Connect to MongoDB
        Client1Local, err := mongo.Connect(context.TODO(), clientOptions)
        Client1 = *Client1Local

或者避免声明局部变量,直接在全局范围内初始化:

    var Client1 *mongo.Client // Note that now Client1 is of *mongo.Client type

    func Connect() {
        // Set client options
        clientOptions := options.Client().ApplyURI("remote_url")

        // Connect to MongoDB
        var err error
        Client1, err = mongo.Connect(context.TODO(), clientOptions) // Now it's an assignment, not a declaration+assignment anymore

更多关于 Golang 的变量阴影讨论在Issue#377 proposal

【讨论】:

  • 哇,感谢您解释问题并解决问题。尽管我确实设法通过使用另一种方法解决了这个问题,但我一直想知道为什么这段代码不起作用。我和你的解释我理解了这个问题。我再次感谢您为提供出色答案所付出的努力。
  • 非常欢迎您 :) 很高兴听到您设法让它正常工作!
【解决方案2】:

尝试包含类似,因为您省略了 db 目录,这可能是问题

import "db/db"

connect.go中还有main(),一个项目应该只有一个主包和main()函数。

---------------- Try what is discussed below exactly ------------

好的,这是我的测试设置,其代码目录树与您的类似:

[user@devsetup src]$ tree test
        test
        ├── dbtest
        │   └── db
        │       └── connect.go
        ├── main // This is executable file
        └── main.go

    2 directories, 3 files

在 connect.go 中我没有改变任何东西,只是删除了上面提到的 main()。 确保只使用导出的函数和变量,导出的函数/变量以大写字母开头。 在 main.go 中看起来像下面的代码。 * 进入 dbtest/db 目录并运行go install 命令。然后转到项目目录,即这里的test,然后运行go build main.go or go build .

package main

import (
        "context"
        "fmt"
        "log"

        "test/dbtest/db"

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

// You will be using this Trainer type later in the program
type Trainer struct {
        Name string
        Age  int
        City string
}

func main() {

        db.Connect()
        collection := db.Client1.Database("test2").Collection("trainers")
        _ = collection

        // fmt.Println("Created collection", _)

        ash := Trainer{"Ash", 10, "Pallet Town"}
        // misty := Trainer{"Misty", 10, "Cerulean City"}
        // brock := Trainer{"Brock", 15, "Pewter City"}

        insertResult, err := collection.InsertOne(context.TODO(), ash)
        if err != nil {
                log.Fatal(err)
        }

        fmt.Println("Inserted a single document: ", insertResult)

        err = db.Client1.Disconnect(context.TODO())

        if err != nil {
                log.Fatal(err)
        }
        fmt.Println("Connection to MongoDB closed.")
}

这是我的二进制输出,因为我没有给出任何输入 url,它抛出了一个错误。似乎工作。我在 main.go 中注释掉了一个包和一行

[user@devsetup test]$ ./test
20xx/yy/zz aa:bb:cc error parsing uri: scheme must be "mongodb" or "mongodb+srv"

【讨论】:

  • 解释了一下,现在试试这个
  • 感谢您的精彩解释,我会尝试并在这里评论结果。
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多