最近在使用Golang 開發使用MongoDB的系統,MongoDB是一個目前非常流行的NO-SQL (Not Only -SQL)資料庫,網路上有很多的介紹了,這邊不多說,使用起來跟關聯式資料庫不太一樣,但由於其彈性及在某些應用情境下的高速,因此也就成了系統開發的一個不可或缺的資料庫選項。
使用MongoDB
在Golang下使用MongoDB並不特別,一樣是先取得好的Go MongoDB套件,如果有爬過一些文,會發現之前很多的部落客會推薦mgo,但是mgo已經停止維護更新了,好像停留在MongoDB v4.3 吧(目前v 7.0),因此建議使用官方推薦的mongo-driver,可以用以下命令取得:
go get go.mongodb.org/mongo-driver/mongo
取得後,如同一般使用資料庫/網路服務/序列服務一樣,先建立Client然後建立連線,mongo-driver新版兩者一次到位,如下(下例使用的是有帳號密碼的連線方式),後面跟著選擇資料庫(Database)、選擇Collection,然後正常使用查詢、CRUD等等。(由於是NO-SQL,跟一般的SQL不太一樣,需要學一下它的一些專門用法及Bson語法)。
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
credential := options.Credential{
Username: "xxxx",
Password: "bbbb",
}
clientOpts := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(credential)
//clientOpts := options.Client().ApplyURI("mongodb://localhost:27017") //沒有帳號密碼下直接連
ctx := context.Background()
client, err := mongo.Connect(ctx, clientOpts)
if err != nil {
fmt.Println(err) //Connect似乎不吐error
return
}
//db
db := client.Database("test")
collectionNames, err := db.ListCollectionNames(ctx, bson.M{})
fmt.Println("collectionNames:", collectionNames)
//collection
collection := db.Collection("member")
fmt.Printf("collection: %s \n", collection.Name())
//後續進行查詢、CRUD等問題
以上一切很棒,使用起來如同預期,直到有一次我密碼輸入錯誤,奇怪,系統在連線時並未返回err,而是直接跑到查詢的時候panic了(導致系統crash),或是連到一個錯誤的位址,也是類似的情況,就好像mongo.Connect不會吐出error。
解法
使用client.Ping()如下,於Connect之後ping一下Server,Ping()在有錯誤的時候會回傳error,例如上述的帳密有錯、server not response等等,都會分別回傳錯誤。
client, err := mongo.Connect(ctx, clientOpts)
err = client.Ping(ctx, nil) //若沒有成功連線,則會返回error
if err != nil {
fmt.Println(err)
return
}原因
身為一個追根究柢的工程師,在能順利處理問題後我們還是想要了解一下原因是甚麼,參考套件中Connect的說明
The Client.Connect method starts background goroutines to monitor the state of the deployment and does not do any I/O in the main goroutine to prevent the main goroutine from blocking. Therefore, it will not error if the deployment is down.
也就是說Connect時並沒有真的去進行Server的I/O,也就不會觸發auth error、server not response error等,而Ping才有真正的進行。
又學到一招~。