[Fiber] A simple introduction to high-performance Web Framework based on FastHttp engine


highlight: xcode

a brief introdction

Fiber is a Web framework inspired by the famous Node.js Web Framework - Express.js . It is built on Fasthttp, which is Go's fastest HTTP engine. Designed to simplify rapid development with zero memory allocation and performance in mind.

Install

First, you need to download and install Go SDK 1.17 or higher.

Enter the following command to install Fiber:

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

zero allocation

*fiber.CtxSome values ​​returned by Fiber are not immutable by default and can be reused across requests. And context values ​​can only be used within handlers, you cannot keep any references to them. After you return from the handler program, any values ​​you obtain from the context can be reused in future requests. Examples are as follows:

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

// ...

} ``` If you need to persist such values ​​outside the handler, use the built-in copy function to copy their buffer. Examples are as follows:

```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

// ...

} 以下示例编写了一个函数,在It is available under the ``gofiber/utils.CopyString` function.

```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