項目名稱你可以取一個你喜歡的名字,比如 golang-api,然后 Next:

接著直接點擊 Create Project 即可:

然后,點擊 Build a Database

選擇免費的 Shared

點擊 Create Cluster 創建集群,需要等一些時間。(其他用默認即可)

接著需要創建能夠訪問該數據庫的用戶。點擊 Create User,如果需要保證安全性,可以限制 IP。然后點擊 Finish and Close 即可。

你也可以不限制 IP,畢竟我們只是練習、測試項目。(如果你下面運行程序,發現連不上 MongoDB,就考慮把 IP 限制直接去掉)

保存后,可以看到 Database Deployments 界面:

初始化 Go 項目

GitHub 創建項目: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

接著在目錄下創建 main.go,輸入如下內容:

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 實現的類似 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、目錄結構

創建如下目錄,注意其中的注釋:

.
├── config 用于項目配置文件
├── controller 用于應用程序邏輯
├── go.mod
├── go.sum  
├── main.go
├── model  用于數據和數據庫邏輯
├── response  用于描述我們希望 API 給出的響應的文件
└── route  用于 URL 模式和處理程序信息

3、配置連接到 MongoDB

為了讓我們的程序連接到數據庫 MongoDB,跟 MySQL 等類似,需要連接字符串。

在上面 MongoDB 的 Database Deployments 頁面,點擊 Connect 按鈕:

接著點擊 Connect your application,然后驅動選擇 Go,及其版本。

然后復制:

設置環境變量

在項目根目錄創建 .env 文件,增加 MONGOURI:

MONGOURI=mongodb+srv://<user>:<password>@cluster0.k0oen.mongodb.net/myFirstDatabase?retryWrites=true&w=majority

注意替換其中的 user 和 password 為你開頭設置的。

接著需要寫代碼讀取環境變量。因為環境變量通過 key=value 的簡單形式保存在文件,因此我們使用一個對應的第三方庫:github.com/joho/godotenv。

在 config 目錄中增加 env.go 文件,輸入如下內容:

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")
}

然后執行 go mod tidy,更新依賴。(這個命令可以多次執行)

連接到 MongoDB

接著在 config 目錄下創建 setup.go 文件,增加如下內容:

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 客戶端實例
var DB *mongo.Client = ConnectDB()

// GetCollection 獲得數據庫集合
func GetCollection(client *mongo.Client, collectionName string) *mongo.Collection {
 collection := client.Database("golangAPI").Collection(collectionName)
 return collection
}

以上代碼簡單解釋下:

以上的設計并不是最好的,主要讓大家熟悉操作 MongoDB 的 API。

4、設置 API 路由處理程序和響應類型

Route Handler

完成后,我們需要在 route 文件夾中創建一個 user_route.go 文件,管理我們應用程序中所有與用戶相關的路由,如下所示:

package routes

import "github.com/gofiber/fiber/v2"

func UserRoute(app *fiber.App) {
 // All routes related to users comes here
}

接下來,修改 main.go,路由交給上面的函數處理:

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")
}

響應類型

接下來,我們需要創建一個可重用的 struct 的來描述我們 API 的響應。為此,在 response 文件夾創建一個user_response.go文件并添加以下內容:

package response

import "github.com/gofiber/fiber/v2"

type UserResponse struct {
 Status  int        json:"status"
 Message string     json:"message"
  Data    interface{} json:"data"
}

上面的代碼片段創建了一個通用的響應類型:UserResponse

5、REST API

接下來,我們需要一個 model 來表示我們的應用程序數據。

為此,我們在 model 中創建 user_model.go 文件并輸入如下內容:

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 庫。

創建 User 端點

有了 model,我們現在可以創建一個函數來創建用戶。

在 controller 文件夾下創建文件 user_controller.go 并添加以下內容:

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})
}

這段代碼比較多,簡單解釋下:

接著在 user_route.go 文件中綁定 API URL 和對應的 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 測試創建用戶:

$ 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 確認,數據有沒有寫入:

其他操作

接下來就是實現查找、更新和刪除。這塊內容不一一細講,只列出關鍵代碼。

先看完整的路由:

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 獲取用戶信息中,因為 userId 是字符串,需要轉為 BSON 的 objectID。MongoDB 庫有一個專門的函數:

objId, _ := primitive.ObjectIDFromHex(userId)

具體的操作 MongoDB 的 API 可以查閱文檔:https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo。

6、結論

本文主要在于帶著大家完成一個基本的 CRUD 工作,讓大家熟悉 Fiber + MongoDB 構建 RESTful API,熟悉工作流程。同時了解相關庫的使用。

本文的完整代碼見: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/

文章轉自微信公眾號@幽鬼

上一篇:

Go Fiber框架測試教程:為開發者釋放API的強大功能

下一篇:

利用Scriptable和百度API:開發你的百度熱搜追蹤工具
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費