Golang for Web(第一部分):使用 Golang 和 Fiber 构建您的第一个 REST API

2025-05-24

Golang for Web(第一部分):使用 Golang 和 Fiber 构建您的第一个 REST API

这是Golang for Web系列的第一部分。我的目标是向新手展示如何通过将大型应用程序拆分成多个小应用程序,轻松地使用 Go 构建 REST API。在这里,我们将使用 Gofiber 构建一个简单的 TODO 应用 Web 服务器,并分离所有路由、控制器等。

Go:一种开源编程语言

Go 是一种开源编程语言,可以轻松构建简单可靠高效的软件。

Go 是由 Google 的 Robert Griesemer、Rob Pike 和 Ken Thompson 设计的一门静态类型编译型编程语言。Go 的语法与 C 语言类似,但具备内存安全、垃圾回收、结构化类型和 CSP 风格的并发性。(来源:维基百科)

有趣的

Golang Web 版 🌐

作为一名 MERN 堆栈开发人员,我发现Fiber Web 框架与 express 非常相似,正如他们所声称的那样,对于 JS 开发人员来说,使用 Golang 构建一个漂亮而令人惊叹的 REST API 非常容易。

Fiber是一个基于 Express 的Web 框架,它基于Go 中最快的HTTP 引擎Fasthttp 构建。其设计初衷是简化快速开发,零内存分配,并注重性能。

在这里查看其惊人的基准性能 - https://docs.gofiber.io/extra/benchmarks

我们要建造什么?🤔

好了,废话不多说🤚现在是时候用 Fiber 来演示一下了。今天我们将用 Fiber 构建一个基本的 TODO 应用。我相信,看完之后,你就能轻松地用 Golang 构建 REST API 了👨🏻‍💻

先决条件📝

  • Golang 语法的基本知识。
  • 您的计算机上已安装 Go 1.14 或更高版本。从此处安装
  • 您的计算机上已安装 Postman 或任何其他相关应用程序。点击此处下载

如果你有这些,那就开始吧🚀

是的,请

让我们开始吧🏁

1. 设置我们的项目

首先,让我们创建一个名为的新目录fiber-todo,并在 VS Code(或任何其他代码编辑器/ IDE)中打开此目录

现在在根目录打开终端并运行命令:

go mod init github.com/<Your_Username>/<Repo_Name>
Enter fullscreen mode Exit fullscreen mode

例子 :

go mod init github.com/devsmranjan/golang-fiber-basic-todo-app
Enter fullscreen mode Exit fullscreen mode

让我们通过运行以下命令在我们的项目中安装光纤:

go get -u github.com/gofiber/fiber/v2
Enter fullscreen mode Exit fullscreen mode

现在在我们的根目录中创建一个名为的文件main.go并创建两个目录routes& controllers

2.创建我们的第一个服务器

现在在里面main.go写入以下代码:

package main

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

func main() {}
Enter fullscreen mode Exit fullscreen mode

好的,你会在这里遇到一些错误,但请继续关注我🤝

现在main()让我们在方法内部启动光纤。

app := fiber.New()
Enter fullscreen mode Exit fullscreen mode

通过以下方式添加我们的第一条路线:

app.Get("/", func(c *fiber.Ctx) error {
    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success":  true,
        "message": "You are at the endpoint 😉",
    })
})
Enter fullscreen mode Exit fullscreen mode

最后,监听 8000 端口的服务器并捕获任何错误。

err := app.Listen(":8000")

if err != nil {
    panic(err)
}
Enter fullscreen mode Exit fullscreen mode

这是我们的最终代码:

package main

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

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

    // give response when at /
    app.Get("/", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(fiber.Map{
            "success":  true,
            "message": "You are at the endpoint 😉",
        })
    })

    // Listen on server 8000 and catch error if any
    err := app.Listen(":8000")

    // handle error
    if err != nil {
        panic(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

现在运行我们的服务器,打开终端并在我们的根目录中运行:

go run main.go
Enter fullscreen mode Exit fullscreen mode

它将显示类似这样的内容


 ┌───────────────────────────────────────────────────┐
 │                    Fiber v2.2.0                   │
 │               http://127.0.0.1:8000               │
 │                                                   │
 │ Handlers ............. 2  Threads ............. 4 │
 │ Prefork ....... Disabled  PID ............. 60983 │
 └───────────────────────────────────────────────────┘

Enter fullscreen mode Exit fullscreen mode

现在打开浏览器,然后转到localhost:8000。您将获得如下输出

{
    "message": "You are at the endpoint 😉",
    "success": true
}
Enter fullscreen mode Exit fullscreen mode

哈哈哈!!!我们成功了🤟

你做到了

此外,如果您想添加记录器中间件,请运行

go get -u github.com/gofiber/fiber/v2/middleware/logger
Enter fullscreen mode Exit fullscreen mode

在我们的项目中导入记录器

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger" // new
)
Enter fullscreen mode Exit fullscreen mode

最后,将这个中间件与我们的app

app.Use(logger.New())
Enter fullscreen mode Exit fullscreen mode

这是我们的最终代码:

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger" // new
)

func main() {
    app := fiber.New()
    app.Use(logger.New()) // new

    // give response when at /
    app.Get("/", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(fiber.Map{
            "success":  true,
            "message": "You are at the endpoint 😉",
        })
    })

    // Listen on server 8000 and catch error if any
    err := app.Listen(":8000")

    // handle error
    if err != nil {
        panic(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

现在再次运行我们的服务器,localhost:8000您可以看到终端显示了我们的请求日志,如下所示:

21:44:48 | 200 |      0s |       127.0.0.1 | GET     | /
Enter fullscreen mode Exit fullscreen mode

3. 确定 TODO 应用的端点

localhost:8000/api/todos

request: GET
description: To get all todos
Enter fullscreen mode Exit fullscreen mode

localhost:8000/api/todos/:id

request: GET
description: Get todo by id
Enter fullscreen mode Exit fullscreen mode

localhost:8000/api/todos

request: POST
input: {
    title : String
}
description: Create new todo
Enter fullscreen mode Exit fullscreen mode

localhost:8000/api/todos/:id

request: PUT
input: {
    title : String,
    completed : Boolean
}
description: Update todo
Enter fullscreen mode Exit fullscreen mode

localhost:8000/api/todos/:id

request: DELETE
description: Delete todo
Enter fullscreen mode Exit fullscreen mode

4. 构建我们的第一个 API 端点

步骤1:

让我们为待办事项应用程序编写第一个控制器。

打开controllers目录并创建名为todo.go

现在controllers/todo.go让我们进行所需的导入。

package controllers

import (
    "github.com/gofiber/fiber/v2"
)
Enter fullscreen mode Exit fullscreen mode

添加Todo结构

type Todo struct {
    Id        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}
Enter fullscreen mode Exit fullscreen mode

让我们添加一些预定义的待办事项

var todos = []*Todo{
    {
        Id:        1,
        Title:     "Walk the dog 🦮",
        Completed: false,
    },
    {
        Id:        2,
        Title:     "Walk the cat 🐈",
        Completed: false,
    },
}
Enter fullscreen mode Exit fullscreen mode

现在我们终于可以创建控制器来获取所有待办事项了

func GetTodos(c *fiber.Ctx) error {
    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todos": todos,
        },
    })
}
Enter fullscreen mode Exit fullscreen mode

这是我们的最终代码controllers/todo.go

package controllers

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

type Todo struct {
    Id        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

var todos = []*Todo{
    {
        Id:        1,
        Title:     "Walk the dog 🦮",
        Completed: false,
    },
    {
        Id:        2,
        Title:     "Walk the cat 🐈",
        Completed: false,
    },
}

// get all todos
func GetTodos(c *fiber.Ctx) error {
    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todos": todos,
        },
    })
}
Enter fullscreen mode Exit fullscreen mode

第2步:

现在让我们为待办事项应用程序编写第一条路线并连接我们的控制器。

打开routes目录并创建一个名为todo.go

现在routes/todo.go让我们进行所需的导入

package routes

import (
    "github.com/gofiber/fiber/v2"
    "github.com/devsmranjan/golang-fiber-basic-todo-app/controllers" // replace
)
Enter fullscreen mode Exit fullscreen mode

替换github.com/devsmranjan/golang-fiber-basic-todo-app/controllers为你的 github repo url,例如github.com/<Your_Username>/<Repo_Name>/controllers

创建第一条获取所有待办事项的路线

func TodoRoute(route fiber.Router) {
    route.Get("", controllers.GetTodos)
}
Enter fullscreen mode Exit fullscreen mode

这是我们的最终代码routes/todo.go

package routes

import (
    "github.com/gofiber/fiber/v2"
    "github.com/devsmranjan/golang-fiber-basic-todo-app/controllers" // replace
)

func TodoRoute(route fiber.Router) {
    route.Get("", controllers.GetTodos)
}
Enter fullscreen mode Exit fullscreen mode

步骤3:

好的,这是最后一步。
返回main.go并导入routes

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/devsmranjan/golang-fiber-basic-todo-app/routes" // new // replace
)
Enter fullscreen mode Exit fullscreen mode

替换github.com/devsmranjan/golang-fiber-basic-todo-app/routes为你的 github repo url 即github.com/<Your_Username>/<Repo_Name>/routes

现在让我们创建一个单独的函数来处理所有的路线。

func setupRoutes(app *fiber.App) {}
Enter fullscreen mode Exit fullscreen mode

将所有路线从main()一个方法移动到setupRoutes()另一个方法。

func setupRoutes(app *fiber.App) {

    // moved from main method
    app.Get("/", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(fiber.Map{
            "success":  true,
            "message": "You are at the endpoint 😉",
        })
    })
}
Enter fullscreen mode Exit fullscreen mode

现在setupRoutes()从方法中调用方法main()

setupRoutes(app)
Enter fullscreen mode Exit fullscreen mode

这是我们的最终main()样子。

func main() {
    app := fiber.New()
    app.Use(logger.New())

    // setup routes
    setupRoutes(app) // new

    // Listen on server 8000 and catch error if any
    err := app.Listen(":8000")

    // handle error
    if err != nil {
        panic(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

现在让我们在方法api中创建一个名为的路由组setupRoutes()

api := app.Group("/api")
Enter fullscreen mode Exit fullscreen mode

/api添加路线响应

api.Get("", func(c *fiber.Ctx) error {
    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "message": "You are at the api endpoint 😉",
    })
})
Enter fullscreen mode Exit fullscreen mode

现在,最后,将所有待办事项路由连接到我们的api路由组

routes.TodoRoute(api.Group("/todos"))
Enter fullscreen mode Exit fullscreen mode

最终setupRoutes()方法如下:

func setupRoutes(app *fiber.App) {
    // give response when at /
    app.Get("/", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(fiber.Map{
            "success":  true,
            "message": "You are at the endpoint 😉",
        })
    })

    // api group
    api := app.Group("/api")

    // give response when at /api
    api.Get("", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(fiber.Map{
            "success": true,
            "message": "You are at the api endpoint 😉",
        })
    })

    // connect todo routes
    routes.TodoRoute(api.Group("/todos"))
}
Enter fullscreen mode Exit fullscreen mode

现在运行服务器并转到http://localhost:8000/api/todos。输出如下所示。

{
    "data": {
        "todos": [
            {
                "id": 1,
                "title": "Walk the dog 🦮",
                "completed": false
            },
            {
                "id": 2,
                "title": "Walk the cat 🐈",
                "completed": false
            }
        ]
    },
    "success": true
}
Enter fullscreen mode Exit fullscreen mode

是的

5. 让我们创建其他控制器🎛

我想你已经明白这一切是怎么运作的了。对吧?😎

现在让我们创建其他控制器。
但在此之前,让我们添加一些必需的导入controllers/todo.go

import (
    "fmt" // new
    "strconv" // new

    "github.com/gofiber/fiber/v2"
)
Enter fullscreen mode Exit fullscreen mode

好的。让我们创建一个控制器来创建待办事项

func CreateTodo(c *fiber.Ctx) error {
    type Request struct {
        Title string `json:"title"`
    }

    var body Request

    err := c.BodyParser(&body)

    // if error
    if err != nil {
        fmt.Println(err)
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success":  false,
            "message": "Cannot parse JSON",
        })
    }

    // create a todo variable
    todo := &Todo{
        Id:        len(todos) + 1,
        Title:     body.Title,
        Completed: false,
    }

    // append in todos
    todos = append(todos, todo)

    return c.Status(fiber.StatusCreated).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todo": todo,
        },
    })
}
Enter fullscreen mode Exit fullscreen mode

通过 id 获取单个待办事项的控制器

func GetTodo(c *fiber.Ctx) error {
    // get parameter value
    paramId := c.Params("id")

    // convert parameter value string to int
    id, err := strconv.Atoi(paramId)

    // if error in parsing string to int
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success":  false,
            "message": "Cannot parse Id",
        })
    }

    // find todo and return
    for _, todo := range todos {
        if todo.Id == id {
            return c.Status(fiber.StatusOK).JSON(fiber.Map{
                "success": true,
                "data": fiber.Map{
                    "todo": todo,
                },
            })
        }
    }

    // if todo not available
    return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
        "success": false,
        "message": "Todo not found",
    })
}
Enter fullscreen mode Exit fullscreen mode

用于更新待办事项的控制器

func UpdateTodo(c *fiber.Ctx) error {
    // find parameter
    paramId := c.Params("id")

    // convert parameter string to int
    id, err := strconv.Atoi(paramId)

    // if parameter cannot parse
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse id",
        })
    }

    // request structure
    type Request struct {
        Title     *string `json:"title"`
        Completed *bool   `json:"completed"`
    }

    var body Request
    err = c.BodyParser(&body)

    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse JSON",
        })
    }

    var todo *Todo

    for _, t := range todos {
        if t.Id == id {
            todo = t
            break
        }
    }

    if todo.Id == 0 {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
            "success":  false,
            "message": "Not found",
        })
    }

    if body.Title != nil {
        todo.Title = *body.Title
    }

    if body.Completed != nil {
        todo.Completed = *body.Completed
    }

    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todo": todo,
        },
    })
}
Enter fullscreen mode Exit fullscreen mode

删除待办事项的控制器

func DeleteTodo(c *fiber.Ctx) error {
    // get param
    paramId := c.Params("id")

    // convert param string to int
    id, err := strconv.Atoi(paramId)

    // if parameter cannot parse
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse id",
        })
    }

    // find and delete todo
    for i, todo := range todos {
        if todo.Id == id {

            todos = append(todos[:i], todos[i+1:]...)

            return c.Status(fiber.StatusNoContent).JSON(fiber.Map{
                "success":  true,
                "message": "Deleted Succesfully",
            })
        }
    }

    // if todo not found
    return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
        "success": false,
        "message": "Todo not found",
    })
}
Enter fullscreen mode Exit fullscreen mode

这是我们的最终代码controllers/todo.go

package controllers

import (
    "fmt"
    "strconv"

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

type Todo struct {
    Id        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

var todos = []*Todo{
    {
        Id:        1,
        Title:     "Walk the dog 🦮",
        Completed: false,
    },
    {
        Id:        2,
        Title:     "Walk the cat 🐈",
        Completed: false,
    },
}

// get all todos
func GetTodos(c *fiber.Ctx) error {
    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todos": todos,
        },
    })
}

// Create a todo
func CreateTodo(c *fiber.Ctx) error {
    type Request struct {
        Title string `json:"title"`
    }

    var body Request

    err := c.BodyParser(&body)

    // if error
    if err != nil {
        fmt.Println(err)
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success":  false,
            "message": "Cannot parse JSON",
        })
    }

    // create a todo variable
    todo := &Todo{
        Id:        len(todos) + 1,
        Title:     body.Title,
        Completed: false,
    }

    // append in todos
    todos = append(todos, todo)

    return c.Status(fiber.StatusCreated).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todo": todo,
        },
    })
}

// get a single todo
// PARAM: id
func GetTodo(c *fiber.Ctx) error {
    // get parameter value
    paramId := c.Params("id")

    // convert parameter value string to int
    id, err := strconv.Atoi(paramId)

    // if error in parsing string to int
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success":  false,
            "message": "Cannot parse Id",
        })
    }

    // find todo and return
    for _, todo := range todos {
        if todo.Id == id {
            return c.Status(fiber.StatusOK).JSON(fiber.Map{
                "success": true,
                "data": fiber.Map{
                    "todo": todo,
                },
            })
        }
    }

    // if todo not available
    return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
        "success": false,
        "message": "Todo not found",
    })
}

// Update a todo
// PARAM: id
func UpdateTodo(c *fiber.Ctx) error {
    // find parameter
    paramId := c.Params("id")

    // convert parameter string to int
    id, err := strconv.Atoi(paramId)

    // if parameter cannot parse
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse id",
        })
    }

    // request structure
    type Request struct {
        Title     *string `json:"title"`
        Completed *bool   `json:"completed"`
    }

    var body Request
    err = c.BodyParser(&body)

    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse JSON",
        })
    }

    var todo *Todo

    for _, t := range todos {
        if t.Id == id {
            todo = t
            break
        }
    }

    if todo.Id == 0 {
        return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
            "success":  false,
            "message": "Not found",
        })
    }

    if body.Title != nil {
        todo.Title = *body.Title
    }

    if body.Completed != nil {
        todo.Completed = *body.Completed
    }

    return c.Status(fiber.StatusOK).JSON(fiber.Map{
        "success": true,
        "data": fiber.Map{
            "todo": todo,
        },
    })
}

// Delete a todo
// PARAM: id
func DeleteTodo(c *fiber.Ctx) error {
    // get param
    paramId := c.Params("id")

    // convert param string to int
    id, err := strconv.Atoi(paramId)

    // if parameter cannot parse
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "success": false,
            "message": "Cannot parse id",
        })
    }

    // find and delete todo
    for i, todo := range todos {
        if todo.Id == id {

            todos = append(todos[:i], todos[i+1:]...)

            return c.Status(fiber.StatusNoContent).JSON(fiber.Map{
                "success":  true,
                "message": "Deleted Succesfully",
            })
        }
    }

    // if todo not found
    return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
        "success": false,
        "message": "Todo not found",
    })
}
Enter fullscreen mode Exit fullscreen mode

6.创建其他路线🚏

让我们为待办事项应用程序创建其他路线。

现在,在里面TodoRoute()添加以下所有路线

route.Post("", controllers.CreateTodo)
route.Put("/:id", controllers.UpdateTodo)
route.Delete("/:id", controllers.DeleteTodo)
route.Get("/:id", controllers.GetTodo)
Enter fullscreen mode Exit fullscreen mode

最后,我们的最终代码如下所示:

package routes

import (
    "github.com/gofiber/fiber/v2"
    "github.com/devsmranjan/golang-fiber-basic-todo-app/controllers" // replace
)

func TodoRoute(route fiber.Router) {
    route.Get("", controllers.GetTodos)
    route.Post("", controllers.CreateTodo) // new
    route.Put("/:id", controllers.UpdateTodo) // new
    route.Delete("/:id", controllers.DeleteTodo) // new
    route.Get("/:id", controllers.GetTodo) // new
}
Enter fullscreen mode Exit fullscreen mode

现在我们已经准备好运行我们的服务器了😎
让我们在 Postman 中测试我们的 API。

7. 测试我们的端点

要获取所有待办事项,请GETlocalhost:8000/api/todos

获取所有待办事项

要通过 ID 获取待办事项,请GETlocalhost:8000/api/todos/:id
此处发出请求,将其替换:id为待办事项id

通过 id 获取 todo

要创建新的待办事项,请在请求正文中向 发出POST请求。localhost:8000/api/todostitle: <String>

创建新的待办事项

好的。让我们检查一下待办事项是否创建成功。再次
发送GET请求以localhost:8000/api/todos获取所有待办事项。

创建新的待办事项后获取所有待办事项

耶!!!🤩

现在,让我们通过在请求正文中发送带有或或两者的PUT请求来更新待办事项。 这里用 todo替换localhost:8000/api/todos/:idtitle: <String>completed: <Boolean>
:idid

更新待办事项

要删除待办事项,请发出DELETE请求,localhost:8000/api/todos/:id
此处:id用待办事项替换id

删除待办事项

Congooooooo 🥳 🥳 🥳 我们做到了 💪🏻

做到了

结论

欲了解更多信息,我建议深入了解此处的文档https://docs.gofiber.io/

这是该项目的 GitHub 链接 - https://github.com/devsmranjan/golang-fiber-basic-todo-app

谢谢你阅读我的文章 🙂 。希望你在这里有所收获。

祝您编码愉快👨‍💻👩‍💻,请继续关注本系列的下一篇文章!

谢谢!别忘了点个♥️并关注我哦 :)

文章来源:https://dev.to/devsmranjan/golang-build-your-first-rest-api-with-fibre-24eh
PREV
每个开发人员都应该知道的 22 个 CSS 技巧和窍门
NEXT
28 个 JavaScript 数组方法:开发人员的速查表