[Fiber]基于FastHttp引擎的高性能Web Framework简单入门


highlight: xcode

简单介绍

Fiber 是一个受著名的 Node.js 的 Web Framework —— Express.js 启发的 Web 框架,建立在 Fasthttp 之上,Fasthttp 是 Go 最快的 HTTP 引擎。旨在简化快速开发,同时考虑零内存分配和性能。

安装

首先,需要下载并安装 Go SDK 1.17 或更高版本。

输入以下命令安装 Fiber:

shell go get github.com/gofiber/fiber/v2

零分配

Fiber 返回的某些值默认情况下,*fiber.Ctx 不是不可变的,可以在请求中重复使用。而且只能在处理程序中使用上下文值,你不能保留任何它们的引用。当你从 handler 程序返回之后,任何你从上下文中获取的值都可以在将来的请求中重复使用。实例如下:

```go func handler(c *fiber.Ctx) error { // Variable is only valid within this handler result := c.Params("foo")

// ...

} ``` 如果需要在 handler 外部对这样值进行持久化,使用内置的拷贝函数拷贝它们的缓冲区。示例如下:

```go func handler(c *fiber.Ctx) error { // Variable is only valid within this handler result := c.Params("foo")

// Make a copy
buffer := make([]byte, len(result))
copy(buffer, result)
resultCopy := string(buffer) 
// Variable is now valid forever

// ...

} `` 以下示例编写了一个函数,在gofiber/utils.CopyString` 函数下是可以用的。

```go app.Get("/:foo", func(c *fiber.Ctx) error { // Variable is now immutable result := utils.CopyString(c.Params("foo"))

// ...

}) ```

你也可以通过设置选项让上下文返回的值不可变,这会让你在任何地方持久化它们。当然,这会以性能作为代价。

go app := fiber.New(fiber.Config{ Immutable: true, })

第一个Hello World

使用 Fiber 内置的 New 函数可以快速构建一个 Web App:

```go package main

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

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

app.Get("/", func(c *fiber.Ctx) error {
    return c.SendString("Hello, World!")
})

app.Listen(":3000")

} ```

输入以下命令启动应用程序:

shell go run server.go

通过浏览器访问 http://localhost:3000 返回 Hello, World! 字符串。

具体使用案例

路由

处理器

注册 HTTP 请求方式对应的处理函数:

```go // HTTP methods func (app *App) Get(path string, handlers ...Handler) Router func (app *App) Head(path string, handlers ...Handler) Router func (app *App) Post(path string, handlers ...Handler) Router func (app *App) Put(path string, handlers ...Handler) Router func (app *App) Delete(path string, handlers ...Handler) Router func (app *App) Connect(path string, handlers ...Handler) Router func (app *App) Options(path string, handlers ...Handler) Router func (app *App) Trace(path string, handlers ...Handler) Router func (app *App) Patch(path string, handlers ...Handler) Router

// Add allows you to specifiy a method as value func (app *App) Add(method, path string, handlers ...Handler) Router

// All will register the route on all HTTP methods // Almost the same as app.Use but not bound to prefixes func (app *App) All(path string, handlers ...Handler) Router ```

examples:

```go // Simple GET handler app.Get("/api/list", func(c *fiber.Ctx) error { return c.SendString("I'm a GET request!") })

// Simple POST handler app.Post("/api/register", func(c *fiber.Ctx) error { return c.SendString("I'm a POST request!") }) ```

Use 函数可以用于中间件包和前缀捕捉器。这些路由将仅仅匹配路径的起始字符串。/john 将会匹配 /john.doe/johnnnnn 等。

go func (app *App) Use(args ...interface{}) Router

examples:

```go // Match any request app.Use(func(c *fiber.Ctx) error { return c.Next() })

// Match request starting with /api app.Use("/api", func(c *fiber.Ctx) error { return c.Next() })

// Match requests starting with /api or /home (multiple-prefix support) app.Use([]string{"/api", "/home"}, func(c *fiber.Ctx) error { return c.Next() })

// Attach multiple handlers app.Use("/api", func(c *fiber.Ctx) error { c.Set("X-Custom-Header", random.String(32)) return c.Next() }, func(c *fiber.Ctx) error { return c.Next() }) ```

路由路径

和请求方法绑定到一起的路由路径定义了请求可以在哪里被处理。路由路径可以是固定的字符串或者是模式串。

examples:

```go // This route path will match requests to the root route, "/": app.Get("/", func(c *fiber.Ctx) error { return c.SendString("root") })

// This route path will match requests to "/about": app.Get("/about", func(c *fiber.Ctx) error { return c.SendString("about") })

// This route path will match requests to "/random.txt": app.Get("/random.txt", func(c *fiber.Ctx) error { return c.SendString("random.txt") }) ```

和 Express.js 框架一样,路由声明的顺序也发挥重要的作用。当一个请求被接收到,路由将会按照它们被声明的顺序进行检查

请求参数

路由参数在路由中是动态元素,可以是具名或者是不具名的的部分。这些部分用于捕获 URL 中它们对应位置的值。以路径中具体的参数名位键,使用 Params 函数可以检索得到的值。

三种用于描述参数字符::+*。贪心参数由通配符 * 或者 加号 + 表示。

路由规则还提供了使用可选参数的可能性,因为有的具名参数被标记了 ? 符号,不像 + 号它不是可选的。你可以使用通配符作为一个可选的贪婪的范围参数。

examples:

```go // Parameters app.Get("/user/:name/books/:title", func(c *fiber.Ctx) error { fmt.Fprintf(c, "%s\n", c.Params("name")) fmt.Fprintf(c, "%s\n", c.Params("title")) return nil }) // Plus - greedy - not optional app.Get("/user/+", func(c *fiber.Ctx) error { return c.SendString(c.Params("+")) })

// Optional parameter app.Get("/user/:name?", func(c *fiber.Ctx) error { return c.SendString(c.Params("name")) })

// Wildcard - greedy - optional app.Get("/user/", func(c *fiber.Ctx) error { return c.SendString(c.Params("")) })

// This route path will match requests to "/v1/some/resource/name:customVerb", // since the parameter character is escaped app.Get("/v1/some/resource/name\:customVerb", func(c *fiber.Ctx) error { return c.SendString("Hello, Community") })

// GET /@v1 // Params: "sign" -> "@", "param" -> "v1" app.Get("/:sign:param", handler)

// GET /api-v1 // Params: "name" -> "v1" app.Get("/api-:name", handler)

// GET /customer/v1/cart/proxy // Params: "1" -> "customer/", "2" -> "/cart" app.Get("/v1/proxy", handler)

// GET /v1/brand/4/shop/blue/xs // Params: "1" -> "brand/4", "2" -> "blue/xs" app.Get("/v1//shop/", handler) ```

参数约束

对应的参数还需要进行校验,如果跟对应的路由参数不匹配,Fiber 直接返回 404。这个特性是受到了 .NET Core 启发。

image.png

路由组

路径

像路由一样,路由组也可以有属于一簇的路径。

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

api := app.Group("/api", middleware) // /api

v1 := api.Group("/v1", middleware) // /api/v1 v1.Get("/list", handler) // /api/v1/list v1.Get("/user", handler) // /api/v1/user

v2 := api.Group("/v2", middleware) // /api/v2 v2.Get("/list", handler) // /api/v2/list v2.Get("/user", handler) // /api/v2/user

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

一组路径可以有一个可选的处理器:

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

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

v1 := api.Group("/v1") // /api/v1 v1.Get("/list", handler) // /api/v1/list v1.Get("/user", handler) // /api/v1/user

v2 := api.Group("/v2") // /api/v2 v2.Get("/list", handler) // /api/v2/list v2.Get("/user", handler) // /api/v2/user

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

组处理器

组处理器可以被用于作为路由路径但是它们必须得有一个 Next 方法这样的话流程才能继续走下去。

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

handler := func(c *fiber.Ctx) error {
    return c.SendStatus(fiber.StatusOK)
}
api := app.Group("/api") // /api

v1 := api.Group("/v1", func(c *fiber.Ctx) error { // middleware for /api/v1
    c.Set("Version", "v1")
    return c.Next()
})
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user

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

} ```

模板

Fiber 提供了一个 Views 接口可以为你提供你自己的模板引擎。

go type Views interface { Load() error Render(io.Writer, string, interface{}, ...string) error }

Views 接口包含了一个 LoadRender 方法,Load 在应用程序初始化的时候被 Fiber 执行以加载或者解析模板。

go // Pass engine to Fiber's Views Engine app := fiber.New(fiber.Config{ Views: engine, // Views Layout is the global layout for all template render until override on Render function. ViewsLayout: "layouts/main" })

Render 方法被链接到了 ctx.Render(),并且接收一个模板名称和绑定的数据。如果在 Render 函数中没有定义布局,它会使用全局的布局。如果 Fiber 配置项 PassLocalToViews 被开启了,那么所有使用 ctx.Locals(key, value) 本地变量设置都会传递给模板。

go app.Get("/", func(c *fiber.Ctx) error { return c.Render("index", fiber.Map{ "hello": "world", }); })

引擎

Fiber 团队维护者模板包用来给模板引擎提供包装器:

```go package main

import ( "log" "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html" )

func main() { // Initialize standard Go html template engine engine := html.New("./views", ".html") // If you want other engine, just replace with following // Create a new engine with django // engine := django.New("./views", ".django")

app := fiber.New(fiber.Config{
    Views: engine,
})
app.Get("/", func(c *fiber.Ctx) error {
    // Render index template
    return c.Render("index", fiber.Map{
        "Title": "Hello, World!",
    })
})

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

} ```

错误处理

校验

钩子函数

变得更快

猜你喜欢

转载自blog.csdn.net/weixin_45254062/article/details/131304593