最近在使用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才有真正的進行。
又學到一招~。