新聞中心
之前分享過一篇文章:《項目實(shí)戰(zhàn):使用 Fiber + Gorm 構(gòu)建 REST API》,數(shù)據(jù)庫使用的是 SQLite。今天分享一篇基于 MongoDB 構(gòu)建 REST API 的文章,使用的依然是 Fiber 框架。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了會昌免費(fèi)建站歡迎大家使用!
1、準(zhǔn)備工作
開始之前,先要準(zhǔn)備好 MongoDB。這里我們不自己安裝 MongoDB,而是使用云。Mongo 提供了免費(fèi)使用的。
配置 MongoDB
如果沒有 MongoDB 賬號,先注冊一個:https://www.mongodb.com/zh-cn/cloud/atlas/register。有賬號直接登錄即可。然后新建一個項目(project):
New Project
項目名稱你可以取一個你喜歡的名字,比如 golang-api,然后 Next:
enter project name
接著直接點(diǎn)擊 Create Project 即可:
Create Project
然后,點(diǎn)擊 Build a Database:
Build a Database
選擇免費(fèi)的 Shared:
Shared highlighted in red
點(diǎn)擊 Create Cluster 創(chuàng)建集群,需要等一些時間。(其他用默認(rèn)即可)
Creating a cluster
接著需要創(chuàng)建能夠訪問該數(shù)據(jù)庫的用戶。點(diǎn)擊Create User,如果需要保證安全性,可以限制 IP。然后點(diǎn)擊 Finish and Close 即可。
Create user
你也可以不限制 IP,畢竟我們只是練習(xí)、測試項目。(如果你下面運(yùn)行程序,發(fā)現(xiàn)連不上 MongoDB,就考慮把 IP 限制直接去掉)
Add IP
保存后,可以看到 Database Deployments 界面:
Database Screen
初始化 Go 項目
在 GitHub 創(chuàng)建項目:fibermongo,clone 到本地,然后初始化:
$ go mod init github.com/programmerug/fibermongo
go: creating new go.mod: module github.com/programmerug/fibermongo
安裝以下兩個依賴:
$ go get -v github.com/gofiber/fiber/v2
$ go get -v go.mongodb.org/mongo-driver/mongo
接著在目錄下創(chuàng)建 main.go,輸入如下內(nèi)容:
package main
import (
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.JSON(&fiber.Map{"welcome": "Hello from Fiber + MongoDB"})
})
app.Listen(":2022")
}
啟動 go run main.go,然后通過 curlie[1] 測試(這是 Go 實(shí)現(xiàn)的類似 curl 工具,易用性類似 httpie):
$ curlie localhost:2022
HTTP/1.1 200 OK
Date: Mon, 07 Feb 2022 09:05:48 GMT
Content-Type: application/json
Content-Length: 40
{
"welcome": "Hello from Fiber + MongoDB"
}
2、目錄結(jié)構(gòu)
創(chuàng)建如下目錄,注意其中的注釋:
.
├── config 用于項目配置文件
├── controller 用于應(yīng)用程序邏輯
├── go.mod
├── go.sum
├── main.go
├── model 用于數(shù)據(jù)和數(shù)據(jù)庫邏輯
├── response 用于描述我們希望 API 給出的響應(yīng)的文件
└── route 用于 URL 模式和處理程序信息
3、配置連接到 MongoDB
為了讓我們的程序連接到數(shù)據(jù)庫 MongoDB,跟 MySQL 等類似,需要連接字符串。
在上面 MongoDB 的 Database Deployments 頁面,點(diǎn)擊 Connect 按鈕:
Connect to database
接著點(diǎn)擊 Connect your application,然后驅(qū)動選擇 Go,及其版本。
connect application
然后復(fù)制:
Copy connection string
設(shè)置環(huán)境變量
在項目根目錄創(chuàng)建 .env 文件,增加 MONGOURI:
MONGOURI=mongodb+srv://:@cluster0.k0oen.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
注意替換其中的 user 和 password 為你開頭設(shè)置的。
接著需要寫代碼讀取環(huán)境變量。因?yàn)榄h(huán)境變量通過 key=value 的簡單形式保存在文件,因此我們使用一個對應(yīng)的第三方庫:github.com/joho/godotenv。
在 config 目錄中增加 env.go 文件,輸入如下內(nèi)容:
package config
import (
"log"
"os"
"github.com/joho/godotenv"
)
func EnvMongoURI() string {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
return os.Getenv("MONGOURI")
}
然后執(zhí)行 go mod tidy,更新依賴。(這個命令可以多次執(zhí)行)
連接到 MongoDB
接著在 config 目錄下創(chuàng)建 setup.go 文件,增加如下內(nèi)容:
package config
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func ConnectDB() *mongo.Client {
client, err := mongo.NewClient(options.Client().ApplyURI(EnvMongoURI()))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
// ping the database
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB")
return client
}
// MongoDB 客戶端實(shí)例
var DB *mongo.Client = ConnectDB()
// GetCollection 獲得數(shù)據(jù)庫集合
func GetCollection(client *mongo.Client, collectionName string) *mongo.Collection {
collection := client.Database("golangAPI").Collection(collectionName)
return collection
}
以上代碼簡單解釋下:
- 導(dǎo)入所需的 MongoDB 依賴
- 創(chuàng)建一個ConnectDB 函數(shù),首先將客戶端配置為使用正確的 URI 并檢查錯誤。其次,我們定義了嘗試連接時要使用的 10 秒超時。第三,檢查連接數(shù)據(jù)庫時是否出錯,如果連接時間超過10秒,則取消連接。最后,我們 ping 數(shù)據(jù)庫以測試我們的連接并返回client實(shí)例。
- 調(diào)用 ConnectDB 創(chuàng)建一個DB變量實(shí)例。這在創(chuàng)建集合時會派上用場。
- 創(chuàng)建一個 GetCollection 函數(shù)獲取 collections。
以上的設(shè)計并不是最好的,主要讓大家熟悉操作 MongoDB 的 API。
4、設(shè)置 API 路由處理程序和響應(yīng)類型
Route Handler
完成后,我們需要在 route 文件夾中創(chuàng)建一個 user_route.go 文件,管理我們應(yīng)用程序中所有與用戶相關(guān)的路由,如下所示:
package routes
import "github.com/gofiber/fiber/v2"
func UserRoute(app *fiber.App) {
// All routes related to users comes here
}
接下來,修改 main.go,路由交給上面的函數(shù)處理:
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/programmerug/fibermongo/route"
)
func main() {
app := fiber.New()
// routes
route.UserRoute(app)
app.Listen(":2022")
}
響應(yīng)類型
接下來,我們需要創(chuàng)建一個可重用的 struct 的來描述我們 API 的響應(yīng)。為此,在 response 文件夾創(chuàng)建一個user_response.go文件并添加以下內(nèi)容:
package response
import "github.com/gofiber/fiber/v2"
type UserResponse struct {
Status int `json:"status"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
上面的代碼片段創(chuàng)建了一個通用的響應(yīng)類型:UserResponse。
5、REST API
接下來,我們需要一個 model 來表示我們的應(yīng)用程序數(shù)據(jù)。
為此,我們在 model 中創(chuàng)建 user_model.go 文件并輸入如下內(nèi)容:
package model
import "go.mongodb.org/mongo-driver/bson/primitive"
type User struct {
ID primitive.ObjectID `json:"id,omitempty"`
Name string `json:"name,omitempty" validate:"required"`
Location string `json:"location,omitempty" validate:"required"`
Title string `json:"title,omitempty" validate:"required"`
}
要解釋的是上面的 tag:validate,這是 github.com/go-playground/validator/v10 庫。
創(chuàng)建 User 端點(diǎn)
有了 model,我們現(xiàn)在可以創(chuàng)建一個函數(shù)來創(chuàng)建用戶。
在 controller 文件夾下創(chuàng)建文件 user_controller.go 并添加以下內(nèi)容:
package controller
import (
"context"
"net/http"
"time"
"github.com/programmerug/fibermongo/config"
"github.com/programmerug/fibermongo/model"
"github.com/programmerug/fibermongo/response"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
var userCollection *mongo.Collection = config.GetCollection(config.DB, "user")
var validate = validator.New()
func CreateUser(c *fiber.Ctx) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var user model.User
defer cancel()
// validate the request body
if err := c.BodyParser(&user); err != nil {
return c.Status(http.StatusBadRequest).JSON(response.UserResponse{Status: http.StatusBadRequest, Message: "error", Data: &fiber.Map{"data": err.Error()}})
}
// use the validator library to validate required fields
if validationErr := validate.Struct(&user); validationErr != nil {
return c.Status(http.StatusBadRequest).JSON(response.UserResponse{Status: http.StatusBadRequest, Message: "error", Data: &fiber.Map{"data": validationErr.Error()}})
}
newUser := model.User{
ID: primitive.NewObjectID(),
Name: user.Name,
Location: user.Location,
Title: user.Title,
}
result, err := userCollection.InsertOne(ctx, newUser)
if err != nil {
return c.Status(http.StatusInternalServerError).JSON(response.UserResponse{Status: http.StatusInternalServerError, Message: "error", Data: err.Error()})
}
return c.Status(http.StatusCreated).JSON(response.UserResponse{Status: http.StatusCreated, Message: "success", Data: result})
}
這段代碼比較多,簡單解釋下:
- 首先導(dǎo)入了相關(guān)的依賴
- 通過 config 中的 GetCollection 函數(shù)創(chuàng)建 userCollection
- 通過 github.com/go-playground/validator/v10 獲得 validater 校驗(yàn)器
- 在 CreateUser 函數(shù)中,我們首先定義了將用戶插入文檔時的 10 秒超時,使用驗(yàn)證器庫驗(yàn)證請求正文和必填字段。如果有錯誤,包裝成 UserResponse 返回了適當(dāng)?shù)南⒑蜖顟B(tài)代碼。其次,我們創(chuàng)建了一個newUser變量,使用userCollection.InsertOne 函數(shù)將其插入并檢查是否有錯誤。最后,如果插入成功,我們會返回正確的響應(yīng)。
接著在 user_route.go 文件中綁定 API URL 和對應(yīng)的 handler:
package route
import (
"github.com/gofiber/fiber/v2"
"github.com/programmerug/fibermongo/controller"
)
func UserRoute(app *fiber.App) {
app.Post("/user", controller.CreateUser)
}
go run main.go 啟動程序,不出意外會看到如下輸出:
$ go run main.go
Connected to MongoDB
┌───────────────────────────────────────────────────┐
│ Fiber v2.26.0 │
│ http://127.0.0.1:2022 │
│ (bound on host 0.0.0.0 and port 2022) │
│ │
│ Handlers ............. 1 Processes ........... 1 │
│ Prefork ....... Disabled PID .............. 7158 │
└───────────────────────────────────────────────────┘
然后通過 curlie 測試創(chuàng)建用戶:
$ curlie POST -d '{
"name": "幽鬼",
"location": "北京",
"title": "Software Engineer"
}' http://localhost:2022/user
會看到如下輸出:
HTTP/1.1 201 Created
Date: Tue, 08 Feb 2022 03:08:17 GMT
Content-Type: application/json
Content-Length: 92
{
"status": 201,
"message": "success",
"data": {
"InsertedID": "6201de338ecf6d62fb799d62"
}
}
然后你可以到 MongoDB 確認(rèn),數(shù)據(jù)有沒有寫入:
insert one
其他操作
接下來就是實(shí)現(xiàn)查找、更新和刪除。這塊內(nèi)容不一一細(xì)講,只列出關(guān)鍵代碼。
先看完整的路由:
package route
import (
"github.com/gofiber/fiber/v2"
"github.com/programmerug/fibermongo/controller"
)
func UserRoute(app *fiber.App) {
app.Post("/user", controller.CreateUser)
app.Get("/user/:userId", controller.GetAUser)
app.Put("/user/:userId", controller.EditAUser)
app.Delete("/user/:userId", controller.DeleteAUser)
app.Get("/users", controller.GetAllUsers)
}
通過 userId 獲取用戶信息中,因?yàn)?userId 是字符串,需要轉(zhuǎn)為 BSON 的 objectID。MongoDB 庫有一個專門的函數(shù):
objId, _ := primitive.ObjectIDFromHex(userId)
具體的操作 MongoDB 的 API 可以查閱文檔:https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo。
6、結(jié)論
本文主要在于帶著大家完成一個基本的 CRUD 工作,讓大家熟悉 Fiber + MongoDB 構(gòu)建 RESTful API,熟悉工作流程。同時了解相關(guān)庫的使用。
本文的完整代碼見:https://github.com/programmerug/fibermongo。
參考文章:https://dev.to/hackmamba/build-a-rest-api-with-golang-and-mongodb-fiber-version-4la0
此外,測試 API 時,大家可以使用自己喜歡的工具,比如 postman。
參考資料
[1]curlie: https://curlie.io/
本文轉(zhuǎn)載自微信公眾號「幽鬼」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系幽鬼公眾號。
本文題目:Go:基于MongoDB構(gòu)建RESTAPI-Fiber版
URL分享:http://fisionsoft.com.cn/article/dhccpgp.html


咨詢
建站咨詢
