<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          項目實戰(zhàn):使用 Fiber + Gorm 構建 REST API

          共 5720字,需瀏覽 12分鐘

           ·

          2022-03-01 15:29

          Fiber 作為一個新的 Go 框架,似乎受追捧程度很高,Star 數(shù)飆升很快。不知道這是不是表明,不少 JS/Node 愛好者開始嘗試學習 Go 了,對 Go 是好事。

          今天這篇文章介紹如何使用 Fiber + Gorm 構建 REST API。

          1 概覽

          在這篇文章中,我們將使用 Fiber[1] 框架,它使用起來非常簡單,有一個很好的抽象層,并且包含我們創(chuàng)建 API 所需的一切。

          關于與數(shù)據(jù)庫的交互,我決定使用 ORM 來使整個過程更簡單、更直觀,因此我決定使用Gorm[2],在我看來,Gorm[3] 是 Go 世界中最受歡迎的 ORM,并且特性很多。

          2 準備工作

          本文基于 Go1.17.5。

          在本地創(chuàng)建一個目錄 fibergorm,然后進入該目錄執(zhí)行如下命令:

          $?go?mod?init?github.com/programmerug/fibergorm
          go:?creating?new?go.mod:?module?github.com/programmerug/fibergorm

          接著執(zhí)行如下命令,安裝我們需要的依賴:(這個先不執(zhí)行,之后通過 go mod tidy 安裝)

          go?get?github.com/gofiber/fiber/v2
          go?get?gorm.io/gorm

          為了方便,本教程中,我們使用 SQLite,因為使用了 Gorm,所以哪種關系型數(shù)據(jù)庫對核心代碼沒有什么影響。

          3 開始編碼

          本文以人類的朋友——狗為例。

          先從定義實體開始,它總共有四個屬性:

          • Name - 狗的名字
          • Age - 狗的年齡
          • Breed - 狗的種族(類型)
          • IsGoodBoy - 狗是否是個好孩子

          類似以下內容:

          //?文件名:entities/dog.go
          package?entities

          import?"gorm.io/gorm"

          type?Dog?struct?{
          ????gorm.Model
          ????Name??????string?`json:"name"`
          ????Age???????int????`json:"age"`
          ????Breed?????string?`json:"breed"`
          ????IsGoodBoy?bool???`json:"is_good_boy"?gorm:"default:true"`
          }

          注意其中的內嵌類型 gorm.Model,它只是定義了一些通用的字段。

          type?Model?struct?{
          ????ID????????uint?`gorm:"primarykey"`
          ????CreatedAt?time.Time
          ????UpdatedAt?time.Time
          ????DeletedAt?DeletedAt?`gorm:"index"`
          }

          因此,我們完全可以自己選擇是否要嵌入 gorm.Model。

          接著,我們配置與數(shù)據(jù)庫的連接。一般我喜歡創(chuàng)建一個名為 Connect() 的函數(shù),它負責初始化連接,此外還負責在我們的數(shù)據(jù)庫中執(zhí)行遷移(migration),即生成表結構:

          //?文件名:config/database.go
          package?config

          import?(
          ????"github.com/programmerug/fibergorm/entities"
          ????"gorm.io/driver/sqlite"
          ????"gorm.io/gorm"
          )

          var?Database?*gorm.DB

          func?Connect()?error?{
          ????var?err?error

          ????Database,?err?=?gorm.Open(sqlite.Open("fibergorm.db"),?&gorm.Config{})

          ????if?err?!=?nil?{
          ????????panic(err)
          ????}

          ????Database.AutoMigrate(&entities.Dog{})

          ????return?nil
          }
          • fibergorm.db 是最后生成的數(shù)據(jù)庫文件

          • 在程序啟動時,需要調用 Connect 函數(shù)

          現(xiàn)在已經定義了實體并配置了到數(shù)據(jù)庫的連接,我們可以開始處理我們的處理程序。我們的每個處理程序都將對應來自 API 的一個路由,每個處理程序只負責執(zhí)行一個操作。首先讓我們獲取數(shù)據(jù)庫表中的所有記錄。

          //?文件名:handlers/dog.go
          package?handlers

          import?(
          ????"github.com/gofiber/fiber/v2"
          ????"github.com/programmerug/fibergorm/config"
          ????"github.com/programmerug/fibergorm/entities"
          )

          func?GetDogs(c?*fiber.Ctx)?error?{
          ????var?dogs?[]entities.Dog

          ????config.Database.Find(&dogs)
          ????return?c.Status(200).JSON(dogs)
          }

          //?...

          現(xiàn)在根據(jù)將在請求參數(shù)中發(fā)送的 id 參數(shù)獲取一條記錄。

          //?文件名:handlers/dog.go
          package?handlers

          //?...

          func?GetDog(c?*fiber.Ctx)?error?{
          ????id?:=?c.Params("id")
          ????var?dog?entities.Dog

          ????result?:=?config.Database.Find(&dog,?id)

          ????if?result.RowsAffected?==?0?{
          ????????return?c.SendStatus(404)
          ????}

          ????return?c.Status(200).JSON(&dog)
          }

          //?...

          現(xiàn)在我們可以得到所有的記錄和根據(jù) id 獲取一條記錄。但缺乏在數(shù)據(jù)庫表中插入新記錄的功能。

          //?文件名:handlers/dog.go
          package?handlers

          //?...

          func?AddDog(c?*fiber.Ctx)?error?{
          ????dog?:=?new(entities.Dog)

          ????if?err?:=?c.BodyParser(dog);?err?!=?nil?{
          ????????return?c.Status(503).SendString(err.Error())
          ????}

          ????config.Database.Create(&dog)
          ????return?c.Status(201).JSON(dog)
          }

          //?...

          我們還需要添加更新數(shù)據(jù)庫中現(xiàn)有記錄的功能。與我們已經實現(xiàn)的類似,使用id參數(shù)來更新特定記錄。

          //?文件名:handlers/dog.go
          package?handlers

          //?...

          func?UpdateDog(c?*fiber.Ctx)?error?{
          ????dog?:=?new(entities.Dog)
          ????id?:=?c.Params("id")

          ????if?err?:=?c.BodyParser(dog);?err?!=?nil?{
          ????????return?c.Status(503).SendString(err.Error())
          ????}

          ????config.Database.Where("id?=??",?id).Updates(&dog)
          ????return?c.Status(200).JSON(dog)
          }

          //?...

          最后,我們需要刪除特定記錄,再次使用 id 參數(shù)從我們的數(shù)據(jù)庫中刪除特定記錄。

          //?文件名:handlers/dog.go
          package?handlers

          //?...

          func?RemoveDog(c?*fiber.Ctx)?error?{
          ????id?:=?c.Params("id")
          ????var?dog?entities.Dog

          ????result?:=?config.Database.Delete(&dog,?id)

          ????if?result.RowsAffected?==?0?{
          ????????return?c.SendStatus(404)
          ????}

          ????return?c.SendStatus(200)
          }

          //?...

          現(xiàn)在只需要創(chuàng)建我們的 main 文件,該文件將負責初始化與數(shù)據(jù)庫的連接以及我們的 API 路由將在何處定義,并且將處理程序與它們進行關聯(lián)綁定。

          //?文件名:main.go
          package?main

          import?(
          ????"log"

          ????"github.com/gofiber/fiber/v2"
          ????"github.com/programmerug/fibergorm/config"
          ????"github.com/programmerug/fibergorm/handlers"
          )

          func?main()?{
          ????app?:=?fiber.New()

          ????config.Connect()

          ????app.Get("/dogs",?handlers.GetDogs)
          ????app.Get("/dogs/:id",?handlers.GetDog)
          ????app.Post("/dogs",?handlers.AddDog)
          ????app.Put("/dogs/:id",?handlers.UpdateDog)
          ????app.Delete("/dogs/:id",?handlers.RemoveDog)

          ????log.Fatal(app.Listen(":3000"))
          }

          至此,我們完成了一個簡單應用的 CRUD。涉及到 fiber 和 gorm 的 API 你應該查閱相關文檔進一步了解。

          最終,項目目錄如下:

          ├──?config
          │???└──?database.go
          ├──?entities
          │???└──?dog.go
          ├──?fibergorm.db
          ├──?go.mod
          ├──?go.sum
          ├──?handlers
          │???└──?dog.go
          └──?main.go

          執(zhí)行 go run main.go:

          $?go?run?main.go

          ?┌───────────────────────────────────────────────────┐
          ?│???????????????????Fiber?v2.24.0???????????????????│
          ?│???????????????http://127.0.0.1:3000???????????????│
          ?│???????(bound?on?host?0.0.0.0?and?port?3000)???????│
          ?│???????????????????????????????????????????????????│
          ?│?Handlers?.............?7??Processes?...........?1?│
          ?│?Prefork?.......?Disabled??PID?.............?89910?│
          ?└───────────────────────────────────────────────────┘

          借助 postman、curl 之類的工具驗證接口的正確性。

          因為 fiber Ctx 的 BodyParser 能夠解析 Context-Type 值是:application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data 等的數(shù)據(jù),所以,驗證 AddDog 的可以采用你喜歡的 Content-Type。

          curl?--location?--request?POST?'http://127.0.0.1:3000/dogs'?\
          --header?'Content-Type:?application/json'?\
          --data?'{name:"旺財",age:3,breed:"狼狗",is_good_boy:true}'

          可以通過下載 https://sqlitebrowser.org/dl/ 這個 SQLite 工具查看數(shù)據(jù)是否保存成功。

          細心的讀者可能會發(fā)現(xiàn),生成的數(shù)據(jù)表字段順序是根據(jù) Dog 中的字段定義順序確定的。有強迫癥的人可能接受不了,因此實際中你可以不嵌入 gorm.Model,而是自己定義相關字段。

          總結

          本文實現(xiàn)了 CRUD 的功能,希望大家實際動手,這樣才能夠真正掌握。

          本文參考 https://dev.to/franciscomendes10866/how-to-build-rest-api-using-go-fiber-and-gorm-orm-2jbe。

          本文完整代碼:https://github.com/programmerug/fibergorm

          參考資料

          [1]

          Fiber: https://gofiber.io/

          [2]

          Gorm: https://gorm.io/

          [3]

          Gorm: https://gorm.io/



          往期推薦


          我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網公司工作,10多年技術研發(fā)與架構經驗!2012 年接觸 Go 語言并創(chuàng)建了 Go 語言中文網!著有《Go語言編程之旅》、開源圖書《Go語言標準庫》等。


          堅持輸出技術(包括 Go、Rust 等技術)、職場心得和創(chuàng)業(yè)感悟!歡迎關注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio

          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷丁香色五月 | 久久99精品久久久久久不卡l中文无码精品 | 亚洲色婷婷网 | 豆花视频一区二区三区在线观看 | 五月天婷婷综合久久 |