Golang中如何从不同包访问MongoDB

Golang中如何从不同包访问MongoDB 在我的网站项目中,我正在使用MongoDB。当我把所有代码都放在主包中并在主函数中启动数据库时,一切运行都很完美。但是当我把代码拆分到不同的包中时,每当我访问使用GetDBCollection()函数的处理程序时,程序就会崩溃。

那么我该如何在handlers包中访问数据库集合呢?

注:抱歉我的英语不好。

以下是我的部分代码:

handlers.go

package handlers

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"github.com/onurcevik/DuyuruTV/database"
	"github.com/onurcevik/DuyuruTV/model"
	"go.mongodb.org/mongo-driver/bson"
	"golang.org/x/crypto/bcrypt"
)

func RegisterEndpoint(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("content-type", "application/json")
	var person model.Person
	var responseResult model.ResponseResult
	_ = json.NewDecoder(r.Body).Decode(&person)
	collection, _ := database.GetDBCollection()
	if err != nil {
		responseResult.Error = err.Error()
		json.NewEncoder(w).Encode(responseResult)
		return
	}

	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
	result, _ := collection.InsertOne(ctx, person)
	json.NewEncoder(w).Encode(result)
	
}

database.go

package database

import (
	"context"
	"log"
	"time"

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

var client *mongo.Client

func GetDBCollection() (*mongo.Collection, error) {
	ctx, err := context.WithTimeout(context.Background(), 30*time.Second)
	client, _ = mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))

	if err != nil {
		log.Fatal(err)
	}
	// Check the connection
	/*
		client.Ping(context.TODO(), nil)
		if err != nil {
			log.Fatal(err)
		}
	*/
	collection := client.Database("duyurutv").Collection("people")
	return collection, nil
}

main.go

package main

import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/onurcevik/DuyuruTV/handlers"
)

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

func main() {
	fmt.Println("Starting the application...")
	router := mux.NewRouter()
	router.HandleFunc("/", handlers.LoginPageHandler).Methods("GET")
	router.HandleFunc("/login", handlers.LoginEndpoint).Methods("POST")
	router.HandleFunc("/register", handlers.RegisterEndpoint).Methods("POST")
	router.HandleFunc("/people", handlers.GetPeopleEndpoint).Methods("GET")
	router.HandleFunc("/addcontent", handlers.AddContentEndpoint).Methods("GET")
	http.ListenAndServe(":8080", router)

}

更多关于Golang中如何从不同包访问MongoDB的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

collection.InsertOnemongo.Connect 都会返回错误,但您没有处理这些错误。只是将它们赋值给下划线变量。这会不会是问题所在?

更多关于Golang中如何从不同包访问MongoDB的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不,我只是通过在main函数中调用这个函数来解决问题

func StartDatabase() {
	ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
	client, _ = mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))

}

在你的代码中,问题出现在 database.goGetDBCollection() 函数中。每次调用这个函数时都会创建一个新的 MongoDB 连接,这会导致资源浪费和潜在的竞争条件。正确的做法是在程序启动时初始化一次数据库连接,然后在不同的包中共享这个连接。

以下是修改后的代码:

database.go

package database

import (
	"context"
	"log"
	"time"

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

var client *mongo.Client
var collection *mongo.Collection

func InitDB() error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	
	var err error
	client, err = mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
	if err != nil {
		return err
	}

	// 测试连接
	err = client.Ping(ctx, nil)
	if err != nil {
		return err
	}

	collection = client.Database("duyurutv").Collection("people")
	log.Println("Connected to MongoDB!")
	return nil
}

func GetDBCollection() *mongo.Collection {
	return collection
}

func CloseDB() {
	if client != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		client.Disconnect(ctx)
	}
}

main.go

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/onurcevik/DuyuruTV/database"
	"github.com/onurcevik/DuyuruTV/handlers"
)

func main() {
	fmt.Println("Starting the application...")
	
	// 初始化数据库连接
	err := database.InitDB()
	if err != nil {
		log.Fatal("Failed to connect to MongoDB:", err)
	}
	defer database.CloseDB()

	router := mux.NewRouter()
	router.HandleFunc("/", handlers.LoginPageHandler).Methods("GET")
	router.HandleFunc("/login", handlers.LoginEndpoint).Methods("POST")
	router.HandleFunc("/register", handlers.RegisterEndpoint).Methods("POST")
	router.HandleFunc("/people", handlers.GetPeopleEndpoint).Methods("GET")
	router.HandleFunc("/addcontent", handlers.AddContentEndpoint).Methods("GET")
	
	log.Println("Server starting on :8080")
	http.ListenAndServe(":8080", router)
}

handlers.go (修改后的 RegisterEndpoint 函数)

func RegisterEndpoint(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("content-type", "application/json")
	var person model.Person
	var responseResult model.ResponseResult
	
	err := json.NewDecoder(r.Body).Decode(&person)
	if err != nil {
		responseResult.Error = err.Error()
		json.NewEncoder(w).Encode(responseResult)
		return
	}

	collection := database.GetDBCollection()
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	
	result, err := collection.InsertOne(ctx, person)
	if err != nil {
		responseResult.Error = err.Error()
		json.NewEncoder(w).Encode(responseResult)
		return
	}
	
	json.NewEncoder(w).Encode(result)
}

主要修改点:

  1. database.go 中添加了 InitDB() 函数来初始化数据库连接
  2. 使用全局变量 collection 来存储集合引用
  3. GetDBCollection() 现在直接返回预先初始化的集合
  4. main.go 中调用 database.InitDB() 来初始化数据库
  5. handlers.go 中正确处理错误

这样修改后,数据库连接只会在程序启动时创建一次,所有包都可以通过 database.GetDBCollection() 安全地访问同一个集合。

回到顶部