使用Fiber+Gorm构建RESTAPI-《GO开发知识笔记》

admin 2025-11-04 01:34:37 编程 来源:ZONE.CI 全球网 0 阅读模式
  • 1 概览
  • 2 准备工作
  • 总结

    Fiber 作为一个新的 Go 框架,似乎受追捧程度很高,Star 数飙升很快。不知道这是不是表明,不少 JS/Node 爱好者开始尝试学习 Go 了,对 Go 是好事。今天这篇文章介绍如何使用 Fiber + Gorm 构建 REST API。

    1 概览

    在这篇文章中,我们将使用 Fiber[1] 框架,它使用起来非常简单,有一个很好的抽象层,并且包含我们创建 API 所需的一切。关于与数据库的交互,我决定使用 ORM 来使整个过程更简单、更直观,因此我决定使用Gorm[2],在我看来,Gorm[3] 是 Go 世界中最受欢迎的 ORM,并且特性很多。

    2 准备工作

    本文基于 Go1.17.5。在本地创建一个目录 fibergorm,然后进入该目录执行如下命令:

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

    接着执行如下命令,安装我们需要的依赖:(这个先不执行,之后通过 go mod tidy 安装)

    1. go env -w GOPROXY=https://goproxy.cn
    2. go get github.com/gofiber/fiber/v2
    3. go get gorm.io/gorm

    为了方便,本教程中,我们使用 SQLite,因为使用了 Gorm,所以哪种关系型数据库对核心代码没有什么影响。本文以人类的朋友——狗为例。先从定义实体开始,它总共有四个属性:

    • Name - 狗的名字
    • Age - 狗的年龄
    • Breed - 狗的种族(类型)
    • IsGoodBoy - 狗是否是个好孩子

    类似以下内容:

    1. // 文件名:entities/dog.go
    2. package entities
    3. import "gorm.io/gorm"
    4. type Dog struct {
    5. gorm.Model
    6. Name string `json:"name"`
    7. Age int `json:"age"`
    8. Breed string `json:"breed"`
    9. IsGoodBoy bool `json:"is_good_boy" gorm:"default:true"`
    10. }

    注意其中的内嵌类型 gorm.Model,它只是定义了一些通用的字段。

    1. type Model struct {
    2. ID uint `gorm:"primarykey"`
    3. CreatedAt time.Time
    4. UpdatedAt time.Time
    5. DeletedAt DeletedAt `gorm:"index"`
    6. }

    因此,我们完全可以自己选择是否要嵌入 gorm.Model。接着,我们配置与数据库的连接。一般我喜欢创建一个名为 Connect() 的函数,它负责初始化连接,此外还负责在我们的数据库中执行迁移(migration),即生成表结构:

    1. // 文件名:config/database.go
    2. package config
    3. import (
    4. "github.com/programmerug/fibergorm/entities"
    5. "gorm.io/driver/sqlite"
    6. "gorm.io/gorm"
    7. )
    8. var Database *gorm.DB
    9. func Connect() error {
    10. var err error
    11. Database, err = gorm.Open(sqlite.Open("fibergorm.db"), &gorm.Config{})
    12. if err != nil {
    13. panic(err)
    14. }
    15. Database.AutoMigrate(&entities.Dog{})
    16. return nil
    17. }
    • fibergorm.db 是最后生成的数据库文件
    • 在程序启动时,需要调用 Connect 函数

    现在已经定义了实体并配置了到数据库的连接,我们可以开始处理我们的处理程序。我们的每个处理程序都将对应来自 API 的一个路由,每个处理程序只负责执行一个操作。首先让我们获取数据库表中的所有记录。

    1. // 文件名:handlers/dog.go
    2. package handlers
    3. import (
    4. "github.com/gofiber/fiber/v2"
    5. "github.com/programmerug/fibergorm/config"
    6. "github.com/programmerug/fibergorm/entities"
    7. )
    8. func GetDogs(c *fiber.Ctx) error {
    9. var dogs []entities.Dog
    10. config.Database.Find(&dogs)
    11. return c.Status(200).JSON(dogs)
    12. }
    13. // ...

    现在根据将在请求参数中发送的 id 参数获取一条记录。

    1. // 文件名:handlers/dog.go
    2. package handlers
    3. // ...
    4. func GetDog(c *fiber.Ctx) error {
    5. id := c.Params("id")
    6. var dog entities.Dog
    7. result := config.Database.Find(&dog, id)
    8. if result.RowsAffected == 0 {
    9. return c.SendStatus(404)
    10. }
    11. return c.Status(200).JSON(&dog)
    12. }
    13. // ...

    现在我们可以得到所有的记录和根据 id 获取一条记录。但缺乏在数据库表中插入新记录的功能。

    1. // 文件名:handlers/dog.go
    2. package handlers
    3. // ...
    4. func AddDog(c *fiber.Ctx) error {
    5. dog := new(entities.Dog)
    6. if err := c.BodyParser(dog); err != nil {
    7. return c.Status(503).SendString(err.Error())
    8. }
    9. config.Database.Create(&dog)
    10. return c.Status(201).JSON(dog)
    11. }
    12. // ...

    我们还需要添加更新数据库中现有记录的功能。与我们已经实现的类似,使用id参数来更新特定记录。

    1. // 文件名:handlers/dog.go
    2. package handlers
    3. // ...
    4. func UpdateDog(c *fiber.Ctx) error {
    5. dog := new(entities.Dog)
    6. id := c.Params("id")
    7. if err := c.BodyParser(dog); err != nil {
    8. return c.Status(503).SendString(err.Error())
    9. }
    10. config.Database.Where("id = ?", id).Updates(&dog)
    11. return c.Status(200).JSON(dog)
    12. }
    13. // ...

    最后,我们需要删除特定记录,再次使用 id 参数从我们的数据库中删除特定记录。

    1. // 文件名:handlers/dog.go
    2. package handlers
    3. // ...
    4. func RemoveDog(c *fiber.Ctx) error {
    5. id := c.Params("id")
    6. var dog entities.Dog
    7. result := config.Database.Delete(&dog, id)
    8. if result.RowsAffected == 0 {
    9. return c.SendStatus(404)
    10. }
    11. return c.SendStatus(200)
    12. }
    13. // ...

    现在只需要创建我们的 main 文件,该文件将负责初始化与数据库的连接以及我们的 API 路由将在何处定义,并且将处理程序与它们进行关联绑定。

    1. // 文件名:main.go
    2. package main
    3. import (
    4. "log"
    5. "github.com/gofiber/fiber/v2"
    6. "github.com/programmerug/fibergorm/config"
    7. "github.com/programmerug/fibergorm/handlers"
    8. )
    9. func main() {
    10. app := fiber.New()
    11. config.Connect()
    12. app.Get("/dogs", handlers.GetDogs)
    13. app.Get("/dogs/:id", handlers.GetDog)
    14. app.Post("/dogs", handlers.AddDog)
    15. app.Put("/dogs/:id", handlers.UpdateDog)
    16. app.Delete("/dogs/:id", handlers.RemoveDog)
    17. log.Fatal(app.Listen(":3000"))
    18. }

    至此,我们完成了一个简单应用的 CRUD。涉及到 fiber 和 gorm 的 API 你应该查阅相关文档进一步了解。最终,项目目录如下:

    1. ├── config
    2. │ └── database.go
    3. ├── entities
    4. │ └── dog.go
    5. ├── fibergorm.db
    6. ├── go.mod
    7. ├── go.sum
    8. ├── handlers
    9. │ └── dog.go
    10. └── main.go

    执行 go run main.go:

    1. $ go run main.go
    2. ┌───────────────────────────────────────────────────┐
    3. │ Fiber v2.24.0 │
    4. │ http://127.0.0.1:3000 │
    5. │ (bound on host 0.0.0.0 and port 3000) │
    6. │ │
    7. │ Handlers ............. 7 Processes ........... 1 │
    8. │ Prefork ....... Disabled PID ............. 89910 │
    9. └───────────────────────────────────────────────────┘

    借助 postman、curl 之类的工具验证接口的正确性。因为 fiber Ctx 的 BodyParser 能够解析 Context-Type 值是:application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data 等的数据,所以,验证 AddDog 的可以采用你喜欢的 Content-Type。

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

    可以通过下载 https://sqlitebrowser.org/dl/ 这个 SQLite 工具查看数据是否保存成功。细心的读者可能会发现,生成的数据表字段顺序是根据 Dog 中的字段定义顺序确定的。有强迫症的人可能接受不了,因此实际中你可以不嵌入 gorm.Model,而是自己定义相关字段。

    总结

    本文实现了 CRUD 的功能,希望大家实际动手,这样才能够真正掌握。本文参考 https://dev.to/franciscomendes10866/how-to-build-rest-api-using-go-fiber-and-gorm-orm-2jbe。本文完整代码:https://github.com/programmerug/fibergorm。

    设置GOLAND:https://blog.csdn.net/tmt123421/article/details/88665248

    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  10