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
collection.InsertOne 和 mongo.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.go 的 GetDBCollection() 函数中。每次调用这个函数时都会创建一个新的 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)
}
主要修改点:
- 在
database.go中添加了InitDB()函数来初始化数据库连接 - 使用全局变量
collection来存储集合引用 GetDBCollection()现在直接返回预先初始化的集合- 在
main.go中调用database.InitDB()来初始化数据库 - 在
handlers.go中正确处理错误
这样修改后,数据库连接只会在程序启动时创建一次,所有包都可以通过 database.GetDBCollection() 安全地访问同一个集合。

