go极速学-Go Fiber 自搭框架脚手架笔记-(1):-

为什么使用go fiber?

出于好奇心,之前就听闻过这个框架,虽然我的不会Express,听说Fiber是一个参考了Express的Web框架,建立在Go语言写的最快的FasthttpHTTP引擎的基础上。

按官网说的:皆在简化 零内存分配和提高性能,以便快速开发。

至于为啥不用Gin,beego,iris,echo,gf·····感觉上面哪些的框架目前市面上应该是已经很多人,有自己的教脚手架了!我自己出于刚重新接触GO回来没多久的!尝鲜的过程中去学东西也是很有感觉的!所以试一试吧!

目前的它已经出到了V2的版本了,和V1的差别还是比较大的!百度一番之后,也没教程!惯例!哈哈搬砖系列~之官网!!

Fiber 的特点(优势)

官网的大佬的给的几个点:

  • 强大的路由
  • 静态文件服务
  • 极限表现
  • 内存占用低
  • API 接口
  • 中间件和Next支持
  • 快速服务器端编程
  • 模版引擎
  • WebSocket 支持
  • 频率限制器
  • 15 种语言

Fiber的限制

由于 Fiber 使用了 unsafe 特性,导致其可能与最新的 Go 版本不兼容。Fiber 2.18.0 已经在 Go 1.14 到 1.17 上验证过。
Fiber 与 net/http 接口不兼容。这意味着你无法使用 gqlen,go-swagger 或者任何其他属于 net/http 生态的项目。

Fiber v2.21.0 版本初步使用

本节内容:

  • 热更新插件使用
  • Fiber app对象的配置项
  • Fiber app路由和路由组
  • Fiber app启动监听自定义(http和https的配置)

1、来自官网的示例代码

1.1 fresh热重启

插件:

1
go复制代码D:\code\go\awesomeProject1>go get github.com/pilu/fresh

使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
makefile复制代码D:\code\go\awesomeProject1>fresh
20:23:57 runner | InitFolders
20:23:57 runner | mkdir ./tmp
20:23:57 runner | mkdir ./tmp: Cannot create a file when that file already exists.
20:23:57 watcher | Watching .
20:23:57 main | Waiting (loop 1)...
20:23:57 main | receiving first event /
20:23:57 main | sleeping for 600 milliseconds
20:23:57 main | flushing events
20:23:57 main | Started! (5 Goroutines)
20:23:57 main | remove tmp\runner-build-errors.log: The system cannot find the file specified.
20:23:57 build | Building...
20:23:58 runner | Running...

自己玩的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

import (
"fmt"

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

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

// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})
// 定义路由
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("你好小钟同学!")
})

app.Listen(":3000")
}

启动图示:

然后访问接口即可:http://127.0.0.1:3000/

其实对比Fastapi的框架的来说的,其实框架这东西多数蕾西,而且也和我们的GIN其实总体是保持差不多的。


1.2 其他官网示例的安利

📖 基础路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
go复制代码func main() {
app := fiber.New()

// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
})

// GET /flights/LAX-SFO
app.Get("/flights/:from-:to", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("💸 From: %s, To: %s", c.Params("from"), c.Params("to"))
return c.SendString(msg) // => 💸 From: LAX, To: SFO
})

// GET /dictionary.txt
app.Get("/:file.:ext", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("📃 %s.%s", c.Params("file"), c.Params("ext"))
return c.SendString(msg) // => 📃 dictionary.txt
})

// GET /john/75
app.Get("/:name/:age/:gender?", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("👴 %s is %s years old", c.Params("name"), c.Params("age"))
return c.SendString(msg) // => 👴 john is 75 years old
})

// GET /john
app.Get("/:name", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("Hello, %s 👋!", c.Params("name"))
return c.SendString(msg) // => Hello john 👋!
})

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

📖 静态文件服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bash复制代码func main() {
app := fiber.New()

app.Static("/", "./public")
// => http://localhost:3000/js/script.js
// => http://localhost:3000/css/style.css

app.Static("/prefix", "./public")
// => http://localhost:3000/prefix/js/script.js
// => http://localhost:3000/prefix/css/style.css

app.Static("*", "./public/index.html")
// => http://localhost:3000/any/path/shows/index/html

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

📖 中间件和Next

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
go复制代码func main() {
app := fiber.New()

// 全局中间件件,对所有的路由生效
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First handler")
return c.Next()
})

// 匹配所有使用 /api开头的路由
app.Use("/api", func(c *fiber.Ctx) error {
fmt.Println("🥈 Second handler")
return c.Next()
})

// 配置多个中间件一起的使用
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()
})

//注册的具体的路由示例,地址为/api/list
app.Get("/api/list", func(c *fiber.Ctx) error {
fmt.Println("🥉 Last handler")
return c.SendString("Hello, World 👋!")
})

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

📖 根据官网扩展示例-获取路径参数(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
go复制代码package main

import (
"fmt"

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

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

// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})


app.Get("/:value", func(c *fiber.Ctx) error {
return c.SendString("value: " + c.Params("value"))
// => Get request with value: hello world
})

app.Listen(":3000")
}

访问地址:http://127.0.0.1:3000/sdf43534
输出的结果是:

1
makefile复制代码value: sdf43534

📖 根据官网扩展示例-获取路径t数(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
go复制代码package main

import (
"fmt"

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

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

// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})

//对参数的校验
app.Get("/:name?", func(c *fiber.Ctx) error {
if c.Params("name") != "" {
return c.SendString("Hello " + c.Params("name"))
// => Hello john
}
return c.SendString("Where is john?")
})

app.Listen(":3000")
}

访问的结果:

1
2
3
4
5
csharp复制代码地址:http://127.0.0.1:3000/name
结果:Hello name
============
地址:http://127.0.0.1:3000
结果:Where is john?

📖 根据官网扩展示例-获取路径t数(3)-通配符的形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
go复制代码package main

import (
"fmt"

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

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

// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})

//对参数的校验
app.Get("/api/*", func(c *fiber.Ctx) error {
return c.SendString("API path: " + c.Params("*"))
// => API path: user/john
})

app.Listen(":3000")
}

访问:

1
2
3
markdown复制代码地址:http://127.0.0.1:3000/api/34534/3453
结果:API path: 34534/3453
============

📖 【新增】多应用和flask和fastapi的多应用有些类似!

1
2
3
4
5
6
7
8
9
css复制代码func main() {
micro := fiber.New()
micro.Get("/doe", func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
app := fiber.New()
app.Mount("/john", micro) // GET /john/doe -> 200 OK
log.Fatal(app.Listen(":3000"))
}

上面的访问的的地址则为:GET /john/doe -> 200 OK

2、 Fiber实例的对象的配置

这官网的就有点不地道,锁好翻译很多种语言了!可惜进入官网还是英文!哈哈
那也只好应啃吧!

其实这个的Fiber实例的对象的配置和我们的之前的fastapi的配置是一个概念,就是对我们的Fiber实例的对象进行特殊的参数配置初始化。

2.1 new使用的是默认的配置

1
css复制代码app := fiber.New()

2.2 自定义定制个人的配置初始化信息

1
2
3
4
5
6
php复制代码app := fiber.New(fiber.Config{
Prefork: true,
CaseSensitive: true,
StrictRouting: true,
ServerHeader: "Fiber",
})

如上面的开启了多进程之后 Prefork: true,:

2.3 配置初始化信息-配置项有哪些?

挑一些比较值得关注的:


  • Prefork: 是否开启多进程
+ 默认值是 false
+ 作用: 是否开启多进程模式,官网说注意点是:注意:如果启用了,应用程序将需要在shell中运行,因为预叉模式设置了环境变量。如果您使用的是Docker,请确保该应用程序是与CMD ./app或CMD ["sh", "-c", "/app"]
+ 示例,如果开启多进程的情况后:
如上面的开启了多进程之后 Prefork: true,:
![](https://gitee.com/songjianzaina/juejin_p15/raw/master/img/c8bf7e99793fecc8ce840aae18138607de350522dfd553a61625850766844adc)

  • ServerHeader: 定义响应头中的Server的标记头
    • 默认值是 : “”
    • 作用:启用Server具有给定值的http标头。
    • 示例,写入 ServerHeader: “Fiber”,:
      那么我们的请求响应头那就有会:


  • CaseSensitive: 路由定义大小写问题的匹配
    • 默认值是 : false
    • 作用:启用后,/Foo和/foo是不同的路由。

  • Immutable :按描述应该是上下文的值是否可复用的问题,以前gin使用的时候也会有这个问题
    • 默认值是 : false
    • 作用:启用后上下文方法返回的所有值都是不可变的。默认情况下,它们在从处理程序返回之前是有效的

  • UnescapePath: 解决的应该是路由中的所有编码字符编码问题

  • ETag: 应该解决缓存的问题

  • BodyLimit:
  • 默认值是:int类型的4 * 1024 * 1024
  • 作用:为请求体设置允许的最大大小,如果大小超过配置的限制,它将发送413 - Request Entity Too Large回应

  • Concurrency:
+ 默认值是:int类型的256 \* 1024
+ 并发连接的最大数量。
  • ReadTimeout:
+ 默认值是:time.Duration
+ 读取请求完成的超时时间显示,默认是不约束。
  • WriteTimeout:
+ 默认值是:time.Duration
+ 写入最长响应时间,默认是不约束。
  • ReadBufferSize:
    请求读取的每个连接缓冲区大小
  • DisableKeepalive:
    禁用“保持活动连接”,服务器将在向客户端发送第一个响应后关闭传入连接。
  • ErrorHandler
  • 默认的全局的错误的异常处理。

2.4 应用静态文件服务提供

2.4.1 不设置虚拟路径

配置静态文件:

如设置静态文件的目录:

1
vbnet复制代码app.Static("/", "./public")

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New(fiber.Config{
Prefork: true,
CaseSensitive: true,
StrictRouting: true,
ServerHeader: "Fiber",
})

app.Static("/", "./public")

// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})

//对参数的校验
app.Get("/api/*", func(c *fiber.Ctx) error {
return c.SendString("API path: " + c.Params("*"))
// => API path: user/john
})

app.Listen(":3000")
}

直接的访问:

1
arduino复制代码http://127.0.0.1:3000/

2.4.2 设置虚拟路径

其中路径实际上不存在于文件系统中,静态方法,为静态目录指定前缀路径

配置静态文件:

如设置静态文件的目录:

1
vbnet复制代码	app.Static("/static", "./public")

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New(fiber.Config{
Prefork: true,
CaseSensitive: true,
StrictRouting: true,
ServerHeader: "Fiber",
})

//app.Static("/", "./public")
app.Static("/static", "./public")
// 定义全局的中间件
app.Use(func(c *fiber.Ctx) error {
fmt.Println("🥇 First 2222handler")
return c.Next()
})

//对参数的校验
app.Get("/api/*", func(c *fiber.Ctx) error {
return c.SendString("API path: " + c.Params("*"))
// => API path: user/john
})

app.Listen(":3000")
}

访问地址:

1
vbnet复制代码http://127.0.0.1:3000/static/hello.html

结果:

2.4.3 更多的静态服务配置项参数

1
2
3
4
5
6
7
8
php复制代码app.Static("/", "./public", fiber.Static{
Compress: true, //是否开启压缩
ByteRange: true, //是否启用字节范围请求。
Browse: true, //是否启用目录浏览
Index: "index.html" //默认的访问
CacheDuration: 10 * time.Second,//缓存时间
MaxAge: 3600,
})

3、 Fiber路由和路由组

3.1 Fiber路由和路由组

其实这个概念和GIN的类似,如果你接触过GIN的话其实都一样的性质。
完整示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
go复制代码package main

import (
"log"

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

func main() {
app := fiber.New(fiber.Config{
Prefork: true,
CaseSensitive: true,
StrictRouting: true,
ServerHeader: "Fiber",
})

handler := func(c *fiber.Ctx) error {
c.Set("X-Custom-Header", "saaaaaaaaaa")
return c.SendString("我是你的谁!111111!")
}
api := app.Group("/api", handler) // /api
v1 := api.Group("/v1", handler) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", handler) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))

app.Listen(":3000")
}

具体结果:

3.2 查看所有的路由信息列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
go复制代码package main

import (
"encoding/json"
"fmt"

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

handler := func(c *fiber.Ctx) error {
c.Set("X-Custom-Header", "saaaaaaaaaa")
return c.SendString("我是你的谁!111111!")
}
api := app.Group("/api", handler) // /api
v1 := api.Group("/v1", handler) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", handler) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user

//打印
data, _ := json.MarshalIndent(app.Stack(), "", " ")
fmt.Println(string(data))

app.Listen(":3000")
}

输出的结果为:

4、 Fiber启动的监听

http的启动监听:

通常我们的启动的,可以定制器的HOST和PORT,Fiber也一样的可以提供:

1
2
3
4
arduino复制代码// 设置启动的监听端口,默认的HOTS的是本地
app.Listen(":8080")
// 自定义启动额HOTS+端口
app.Listen("127.0.0.1:8080")

https的启动监听:

1
arduino复制代码app.ListenTLS(":443", "./cert.pem", "./cert.key");

还可以对https进行配置:

1
2
3
4
5
6
7
yaml复制代码&tls.Config{
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
Certificates: []tls.Certificate{
cert,
},
}

使用net.Listen来启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
go复制代码package main

import (
"crypto/tls"
"net"

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

handler := func(c *fiber.Ctx) error {
c.Set("X-Custom-Header", "saaaaaaaaaa")
return c.SendString("我是你的谁!111111!")
}
api := app.Group("/api", handler) // /api
v1 := api.Group("/v1", handler) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", handler) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user

//打印
//data, _ := json.MarshalIndent(app.Stack(), "", " ")
//fmt.Println(string(data))

ln, _ := net.Listen("tcp", ":3000")
cer, _ := tls.LoadX509KeyPair("server.crt", "server.key")
ln = tls.NewListener(ln, &tls.Config{Certificates: []tls.Certificate{cer}})
app.Listener(ln)
}

5、 Fiber请求上下文篇

5.1 添加响应头信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
go复制代码package main

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

app.Get("/", func(c *fiber.Ctx) error {
c.Accepts("png")
//c.Accepts("json", "text") // "json"
//c.Accepts("application/json") // "application/json"

//新增的响应头信息---下面的字段会出现再响应头
c.Append("Link", "Test")
c.Append("Link", "http://google.com", "http://localhost")

//返回的APP路由堆栈
return c.JSON(c.App().Stack())
})

app.Listen(":3000")
}

结果:

image.png

其他设置响应的方法 c.Set():

1
2
3
4
5
6
go复制代码app.Get("/", func(c *fiber.Ctx) error {
c.Set("Content-Type", "text/plain")
// => "Content-type: text/plain"
// ...
c.Vary("Accept-Encoding", "Accept")
})

5.2 返回JSON格式数据

1
javascript复制代码  return c.JSON(c.App().Stack())

完整示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
go复制代码package main

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

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

type SomeStruct struct {
Name string
Age uint8
}
app.Get("/json1", func(c *fiber.Ctx) error {
// Create data struct:
data := SomeStruct{
Name: "Grame",
Age: 20,
}
return c.JSON(data)
})
app.Get("/json2", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"name": "Gram222e",
"age": 2000,
})

})

app.Listen(":3000")
}

或者链式的返回:

1
2
3
javascript复制代码return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
})

5.3 获取请求的baseurl和hotsname

1
2
less复制代码fmt.Println("c.BaseURL()", c.BaseURL())
fmt.Println("c.Hostname()", c.Hostname())

image.png

5.4 获取POST提交的body参数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
go复制代码package main


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

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

app.Post("/", func(c *fiber.Ctx) error {
// Get raw body from POST request:
return c.Send(c.Body()) // []byte("user=john")
})

app.Listen(":3000")
}

结果:
image.png

5.5 POST中的body参数绑定解析

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
go复制代码package main

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

type Person struct {
Name string `json:"name" xml:"name" form:"name"`
Pass string `json:"pass" xml:"pass" form:"pass"`
}

app.Post("/", func(c *fiber.Ctx) error {
p := new(Person)
if err := c.BodyParser(p); err != nil {
return err
}
return c.JSON(p)
})

app.Listen(":3000")
}

结果:

image.png

5.6 Cookie设置和删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
go复制代码package main

import (
"time"

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

type Cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Path string `json:"path"`
Domain string `json:"domain"`
MaxAge int `json:"max_age"`
Expires time.Time `json:"expires"`
Secure bool `json:"secure"`
HTTPOnly bool `json:"http_only"`
SameSite string `json:"same_site"`
}

app.Get("/", func(c *fiber.Ctx) error {
cookie := new(fiber.Cookie)
cookie.Name = "john"
cookie.Value = "doe"
cookie.Expires = time.Now().Add(24 * time.Hour)
// Set cookie
c.Cookie(cookie)
return c.SendString("设置cookie成功!")
})

app.Post("/", func(c *fiber.Ctx) error {
//删除所有的ClearCookie
c.ClearCookie()
// 根据键值对删除
c.ClearCookie("user")
return c.SendString("删除cookie成功!")
})

app.Listen(":3000")
}

5.7 文件下载和发送文件

  • 下载文件示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go复制代码package main

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

app.Get("/", func(c *fiber.Ctx) error {
//return c.Download("./files/report-12345.pdf");
// => Download report-12345.pdf
return c.Download("./小同学.txt", "小钟同学的密码文件.txt")
// => Download report.pdf
})

app.Listen(":3000")
}

结果:

image.png


  • 发送文件示例代码:

从给定路径传输文件。设置内容-类型响应HTTP报头字段

PS:发送文件时候,默认的是开启了gzipping的压缩机制,如果需要关闭,设置为false即可,如下

1
arduino复制代码c.SendFile("./static/index.html", false);

演示文件结构:

image.png
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
go复制代码package main

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

func main() {
app := fiber.New()
app.Get("/sendfile", func(c *fiber.Ctx) error {
return c.SendFile("./public/hello.html")
// Disable compression
//return c.SendFile("./static/index.html", false);
})

app.Listen(":3000")
}

执行:

image.png

5.8 上传文件-获取表单文件内容

番外篇说:

  • 1:form-data主要是以键值对的形式来上传参数,同时参数之间以&分隔符分开,同时也可以上传文件,文件上传要指定文件类型。

image.png

  • 2:x-www-form-urlencode 这种参数的传递与form-data最大的区别是,x-www-form-urlencode只能是以键值对的形式传参,但是不可以上传文件。

按名称检索MultipartForm文件,第一返回来自给定密钥的文件

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
//app.Server().MaxConnsPerIP = 1

app.Post("/", func(c *fiber.Ctx) error {
// Get first file from form field "document":
//MultipartForm()。这将返回一个map[string][]string
file, _ := c.FormFile("5gmsg.conf")
// Save file to root directory:
fmt.Println("文件名称", file.Filename)
return c.SaveFile(file, fmt.Sprintf("./%s", file.Filename))
})

app.Listen(":3000")
}

代码执行结果:

image.png

执行上传后:

image.png

5.9 多文件接收-获取表单文件内容

示例代码:

1
css复制代码

package main

import (
“fmt”

“github.com/gofiber/fiber/v2”
)

func main() {
app := fiber.New()
app.Post(“/“, func(c *fiber.Ctx) error {
//MultipartForm()。这将返回一个map[string][]string
if form, err := c.MultipartForm(); err == nil {
fmt.Println(“输出表单信息,”, form)
files := form.File[“5gmsg.conf”]
fmt.Println(“输出files信息,”, files)
for _, file := range files {
fmt.Println(file.Filename, file.Size, file.Header[“Content-Type”][0])
if err := c.SaveFile(file, fmt.Sprintf(“./%s”, file.Filename)); err != nil {
return c.SendString(“上传失败!”)
}
}
}
return c.SendString(“上传成功!”)

})

app.Listen(“:3000”)
}

1
2


代码执行结果:

image.png

执行上传后:

image.png

5.10 获取表单值内容信息

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Post("/", func(c *fiber.Ctx) error {
//MultipartForm()。这将返回一个map[string][]string
fmt.Println("name表单值信息", c.FormValue("name"))
fmt.Println("age表单值信息", c.FormValue("age"))
return c.SendString(fmt.Sprintf("%s-%s-%s", "表单值信息为:", c.FormValue("name"), c.FormValue("age")))

})

app.Listen(":3000")
}

输出结果:

image.png

5.11 获取自定义的请求头信息

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
//MultipartForm()。这将返回一个map[string][]string

c.Get("Content-Type") // "text/plain"

return c.SendString(fmt.Sprintf("%s-%s-%s", "请求头信息为:", c.Get("Content-Type"), c.Get("xiaozhong")))

})

app.Listen(":3000")
}

示例:

image.png

5.12 获取客户端请求IP信息

1
scss复制代码c.IP(), c.IPs()

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
//MultipartForm()。这将返回一个map[string][]string

return c.SendString(fmt.Sprintf("%s-%s-%s", "请求IP信息为:", c.IP(), c.IPs()))

})

app.Listen(":3000")
}

执行截图:

image.png

5.13 判断Content-Type类型和是否XHR请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
go复制代码package main

import (
"fmt"

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

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

app.Get("/", func(c *fiber.Ctx) error {
c.Is("html") // true
c.Is(".html") // true
c.Is("json") // false
c.XHR() // 判断是否XHRjQuery提交
return c.SendString(fmt.Sprintf("%s-%s-%s", "请求IP信息为:", c.Is("html"), c.Is(".html"), c.Is("json")))
})

app.Listen(":3000")
}

5.14 存贮变量传递(中间件之间的信息传递)

这个其实对后续的鉴权非常有用滴,比如我的鉴权完成后,穿得TOKEN到下一个接口!

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

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

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

//全局的中间件中我们的设置一个参数值信息---
app.Use(func(c *fiber.Ctx) error {
c.Locals("user", "小钟同学-变量存贮传递")
return c.Next()
})
app.Get("/", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"name": c.Locals("user"),
"age": 2000,
})
})

app.Listen(":3000")
}

执行结果:

image.png

5.15 301或302的重定向


示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go复制代码package main

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

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

//全局的中间件中我们的设置一个参数值信息---
app.Get("/coffee", func(c *fiber.Ctx) error {
return c.Redirect("/teapot")
})
app.Get("/teapot", func(c *fiber.Ctx) error {
return c.Status(fiber.StatusTeapot).SendString("我是重定向过来的!")
})

app.Listen(":3000")
}

访问地址:http://127.0.0.1:3000/coffee
执行结果:

image.png


其他示例:

1
2
3
4
5
6
kotlin复制代码app.Get("/", func(c *fiber.Ctx) error {
return c.Redirect("/foo/bar")
return c.Redirect("../login")
return c.Redirect("http://example.com")
return c.Redirect("http://example.com", 301)
})

5.16 Params参数-获取path参数


代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/user/:name", func(c *fiber.Ctx) error {
c.Params("name")
return c.SendString(fmt.Sprintf("%s-%s", "获取路径参数上的name值:", c.Params("name")))
})

app.Listen(":3000")
}

访问地址:

1
arduino复制代码http://127.0.0.1:3000/user/nihao

执行结果:

image.png


复杂匹配示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/user/:name", func(c *fiber.Ctx) error {
c.Params("name")
return c.SendString(fmt.Sprintf("%s-%s", "获取路径参数上的name值:", c.Params("name")))
})
app.Get("/user2/*", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("%s-%s-%s", "获取路径参数上的name值:", c.Params("*"), c.Params("*1")))
})

app.Listen(":3000")
}

可以访问的地址:

1
2
3
bash复制代码http://127.0.0.1:3000/user2/nihao/3453
http://127.0.0.1:3000/user2/nihao3453
http://127.0.0.1:3000/user2/nihao=3453

image.png
image.png

image.png

5.17 获取Query参数和QueryParser参数解析


获取参数示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/user", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("%s-%s-%s", "获取路径参数上的name值:", c.Query("name"), c.Query("age")))
})

app.Listen(":3000")
}

请求返回:

image.png


示例绑定解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

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

type Person struct {
Name string `query:"name"`
Age string `query:"age"`
}

func main() {
app := fiber.New()
app.Get("/user", func(c *fiber.Ctx) error {
p := new(Person)
if err := c.QueryParser(p); err != nil {
return err
}
return c.JSON(p)
})

app.Listen(":3000")
}

请求执行:

image.png


获取是有请求路径和参数信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New()
app.Get("/user", func(c *fiber.Ctx) error {

return c.SendString(fmt.Sprintf("%s-%s", "获取访问地址信息:", c.OriginalURL()))
})

app.Listen(":3000")
}

执行结果:

image.png

5.18 响应字节流数据

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go复制代码package main

import (
"bytes"

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

func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.Send([]byte("Hello, World!")) // => "Hello, World!"
})
app.Get("/user", func(c *fiber.Ctx) error {
return c.SendStream(bytes.NewReader([]byte("Hello, World!"))) // => "Hello, World!"
})

app.Listen(":3000")
}

字节流信息的追加写入:

1
2
3
4
5
6
7
8
go复制代码
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
c.Write([]byte("Hello, World!111")) // => "Hello, World!"
c.Write([]byte("Hello, World!222")) // => "Hello, World!"
c.Status(200)
return nil
})

执行结果:

image.png

5.19 响应码和响应体同时设置

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
go复制代码package main

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

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

//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
c.Status(200)
return nil
})

app.Get("/ok2", func(c *fiber.Ctx) error {
return c.Status(400).SendString("Bad Request")
})

app.Get("/ok3", func(c *fiber.Ctx) error {
return c.Status(404).SendFile("./public/gopher.png")
})
app.Listen(":3000")
}

5.20 自定义404的错误响应处理

PS:关键坑点:这个的404自定义的话,你需要放到当所有的路由都注册完成后才可以天机,不然它所有的地址都会找不到!
PS:关键坑点:这个的404自定义的话,你需要放到当所有的路由都注册完成后才可以天机,不然它所有的地址都会找不到!
PS:关键坑点:这个的404自定义的话,你需要放到当所有的路由都注册完成后才可以天机,不然它所有的地址都会找不到!

主要还是使用中间件的方式来处理。

错误的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
go复制代码package main

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

func main() {
app := fiber.New()
//坑点注意了!!!!!
//坑点注意了!!!!!
//坑点注意了!!!!!
app.Use(func(c *fiber.Ctx) error {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"code": "404",
"msg": "找不到这个地址啊!你估计是搞错地址了!",
})
})
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

// 设置全局错误
app.Use(recover.New(recover.Config{
//Next: func(c *fiber.Ctx) bool {
// return c.Query("refresh") == "true"
//},
EnableStackTrace: true,
StackTraceHandler: func(e interface{}) {
//堆栈信息

},
}))
// This panic will be catch by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("I'm an error")
})
app.Listen(":3000")
}

正确的应该是放最后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
go复制代码package main

import (
"fmt"

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

func main() {

app := fiber.New(fiber.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {

return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": fiber.StatusInternalServerError,
"msg": err.Error()},
)
},
})

//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

// 设置全局错误
app.Use(recover.New(recover.Config{
//Next: func(c *fiber.Ctx) bool {
// return c.Query("refresh") == "true"
//},
EnableStackTrace: true,
StackTraceHandler: func(e interface{}) {
//堆栈信息

},
}))
// This panic will be catch by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("大爷!")
})

//放到最后来啊!
app.Use(func(c *fiber.Ctx) error {
fmt.Println(c)
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"code": "404",
"msg": "找不到这个地址啊!你估计是搞错地址了!",
})
})

app.Listen(":3000")
}

执行访问:

image.png

6、 Fiber 中间件篇

来自官网的文档的搬砖系列!

6.1 前言:

Fiberv1和Fiberv2的中间件有区别,

Fiberv2中的中间件必须有return c.next()才可以!

其实这个中间件和我们的所知的fastapi和gin的大致的功能是一样的,都是类似的钩子函数一样的。

在FiberV2中它自己内置了很多的中间件:

  • 用于基础使用用户名和密码认证的中间件 - BasicAuth
  • 缓存作用的中间件 - Cache
  • 压缩使用的中间件件 - Compress
  • 跨域中间件- CORS
  • 过期设置的中间件- ETag
  • 设置访问的Favicon图标的中间件
  • 配置静态文件服务的一些配置信息中间件-# FileSystem
  • 限流中间件 -# Limiter
  • 性能分析中间件 -# Pprof
  • 日志记录中间件 -# Logger
  • 全局异常捕获Recover中间件
  • 代理请求访问中间件
  • 全局链路追踪RequestID中间件
  • Session处理中间件
  • 接口请求超时限制的Timeout中间件

下面我的开始搬砖了!!!我就挑几个聊聊!一一的实践一下看看具体的中间件玩法!

6.2 BasicAuth用户名密码基础认证中间件

首先BasicAuth其实就是请求的时候,你需要提供用户名和账号,来验证!

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
go复制代码package main

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

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

// 配置我们基础的认证的需要的用户和密码信息-----简单的配置
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
"name": "xiaozhong",
"password": "123456",
},
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("basicauth 认证的处理成功!!")

})

app.Listen(":3000")
}

浏览器访问吧!这样明细:然后访问地址:

image.png

此时需要你提供用户名和密码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
go复制代码package main

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

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

// 配置我们基础的认证的需要的用户和密码信息-----简单的配置
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
"xiaozhong": "123456",
"tongxue": "123456",
},
Realm: "Forbidden",
Authorizer: func(user, pass string) bool {
if user == "xiaozhong" && pass == "123456" {
return true
}
if user == "tongxue" && pass == "123456" {
return true
}
return false
},
//认证失败,机型让它弹出窗口!!!!!
//Unauthorized: func(c *fiber.Ctx) error {
//
// return c.Status(200).SendString("basicauth 认证的失败!!!!非法访问!")
//},
ContextUsername: "_user",
ContextPassword: "_pass",
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("basicauth 认证的处理成功!!")
})

app.Listen(":3000")
}

输入用户名和密码:

image.png

image.png

image.png

6.3 跨域中间件

  • 跨域默认配置
1
2
3
4
5
6
7
8
9
yaml复制代码var ConfigDefault = Config{
Next: nil,
AllowOrigins: "*",
AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH",
AllowHeaders: "",
AllowCredentials: false,
ExposeHeaders: "",
MaxAge: 0,
}
  • 跨域中间件使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

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

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

app.Use(cors.New())
// Or extend your config for customization
app.Use(cors.New(cors.Config{
AllowOrigins: "https://gofiber.io, https://gofiber.net",
AllowHeaders: "Origin, Content-Type, Accept",
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("basicauth 认证的处理成功!!")
})

app.Listen(":3000")
}

6.4 限流中间件

  • 限流中间件件默认配置
1
2
3
4
5
6
7
8
9
10
go复制代码var ConfigDefault = Config{
Max: 5,
Expiration: 1 * time.Minute,
KeyGenerator: func(c *fiber.Ctx) string {
return c.IP()
},
LimitReached: func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusTooManyRequests)
},
}
  • 限流中间件使用:

示例:5秒内最多给2个访问!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
go复制代码package main

import (
"time"

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

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

app.Use(limiter.New(limiter.Config{
Next: nil,
Max: 2,
// 5秒内最多给访问2个
Expiration: 5 * time.Second,
KeyGenerator: func(c *fiber.Ctx) string {
return c.Get("x-forwarded-for")
},
LimitReached: func(c *fiber.Ctx) error {
return c.Status(429).SendString("你丫的访问这么快!!!")
},
//Store: myCustomStore{}
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("basicauth 认证的处理成功!!")
})

app.Listen(":3000")
}

超过的时候:
image.png
正常的时候:

image.png

6.5 日志中间件

官网文档中提示提供的很多的参数:

甚至它还已经包括了响应体了内容了!!!不需要我fastapi那样还需要自己去写一次了!!!好像可以哟!哈哈

如,日志中可以记录的常量信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ini复制代码// Logger variables
const (
TagPid = "pid"
TagTime = "time"
TagReferer = "referer"
TagProtocol = "protocol"
TagIP = "ip"
TagIPs = "ips"
TagHost = "host"
TagMethod = "method"
TagPath = "path"
TagURL = "url"
TagUA = "ua"
TagLatency = "latency"
TagStatus = "status" // response status
TagResBody = "resBody" // response body
TagQueryStringParams = "queryParams" // request query parameters
TagBody = "body" // request body
TagBytesSent = "bytesSent"
TagBytesReceived = "bytesReceived"
TagRoute = "route"
TagError = "error"
TagHeader = "header:" // request header
TagQuery = "query:" // request query
TagForm = "form:" // request form
TagCookie = "cookie:" // request cookie
TagLocals = "locals:"
// colors
TagBlack = "black"
TagRed = "red"
TagGreen = "green"
TagYellow = "yellow"
TagBlue = "blue"
TagMagenta = "magenta"
TagCyan = "cyan"
TagWhite = "white"
TagReset = "reset"
)

默认的日志中间件的配置:

1
2
3
4
5
6
7
8
kotlin复制代码var ConfigDefault = Config{
Next: nil,
Format: "[${time}] ${status} - ${latency} ${method} ${path}\n",
TimeFormat: "15:04:05",
TimeZone: "Local",
TimeInterval: 500 * time.Millisecond,
Output: os.Stderr,
}
  • Next:是处理是否传递到下一个的,可以自定义
  • Format:定义日志记录的格式
  • TimeFormat:日志的记录的时间格式
  • TimeZone:日志记录的时间时区
  • TimeInterval:时间即那个
  • Output:输出到哪里,默认的是控制台

默认的日志配置

1
less复制代码app.Use(logger.New())

然后请求接口控制台会输出日志信息:

image.png

添加全局追踪ID日志配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

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

func main() {
app := fiber.New()
app.Use(requestid.New())
app.Use(logger.New(logger.Config{
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
TimeFormat: "02-Jan-2006",
TimeZone: "Asia/Shanghai",
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

app.Listen(":3000")
}

上面的示例,执行后,我完全没看到有requestid

所以继续往下试一试下入文件看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
go复制代码package main

import (
"log"
"os"

"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/requestid"
)

func main() {
app := fiber.New()
app.Use(requestid.New())
file, err := os.OpenFile("./req.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer file.Close()
app.Use(logger.New(logger.Config{
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
TimeFormat: "02-Jan-2006",
TimeZone: "Asia/Shanghai",
Output: file,
}))
//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

app.Listen(":3000")
}

查看我们的日志文件/req.log:

1
2
3
bash复制代码15784 9e7bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1
15784 9f7bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1
15784 a07bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1

嗯嗯,算是看了!!!!

6.6 全局异常中间件

  • 默认的配置信息:
1
2
3
4
5
yaml复制代码var ConfigDefault = Config{
Next: nil,
EnableStackTrace: false,
StackTraceHandler: defaultStackTraceHandler,
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
go复制代码package main

import (
"github.com/gofiber/fiber/v2/middleware/recover"

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

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

//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

app.Use(recover.New())
// This panic will be catch by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("I'm an error")
})
app.Listen(":3000")
}

执行结果:

image.png

这里有疑问,我想捕获我自己定义现实怎么显示呢?
一个自定义的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
go复制代码package main

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

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

//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

// 设置全局错误
app.Use(recover.New(recover.Config{
//Next: func(c *fiber.Ctx) bool {
// return c.Query("refresh") == "true"
//},
EnableStackTrace: true,
StackTraceHandler: func(e interface{}) {
//堆栈信息

},
}))
// This panic will be catch by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("I'm an error")
})
app.Listen(":3000")
}

好像还是有点迷糊?如果全局的处理错误呐?
会看我们的fiber.New配置项中其实有一个ErrorHandler,我们只需要在这个地方定义我们的自己的处理器就可以了!!!

自定义全局异常处理函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
go复制代码package main

import (
"fmt"

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

func main() {
app := fiber.New(fiber.Config{
// Override default error handler
ErrorHandler: func(ctx *fiber.Ctx, err error) error {
//获取当前的异常响应码
code := fiber.StatusInternalServerError
// 如果有自定义的响应码的话,那么就返回自己的自定义的响应码信息
if e, ok := err.(*fiber.Error); ok {
code = e.Code
}
fmt.Println(code)
fmt.Println(err)
// 发送自定义的异常错误的响应页面
//err = ctx.Status(code).SendFile(fmt.Sprintf("./%d.html", code))
err = ctx.JSON(fiber.Map{
"code": code,
"msg": err.Error(),
})
// 如果找不到这个页面,那么就直接其他其他的异常
if err != nil {
// In case the SendFile fails
return ctx.Status(fiber.StatusInternalServerError).SendString("程序员哥哥睡眠不足,系统崩溃了!")
}
// 返回这个函数
return nil
},
})

//仅仅是设置响应码信息
app.Get("/ok1", func(c *fiber.Ctx) error {
return c.Status(200).SendString("日志记录!!!")
})

// 设置全局错误
app.Use(recover.New(recover.Config{
//Next: func(c *fiber.Ctx) bool {
// return c.Query("refresh") == "true"
//},
EnableStackTrace: true,
StackTraceHandler: func(e interface{}) {
//堆栈信息

},
}))
// This panic will be catch by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("我是故意的!")
})
app.Listen(":3000")
}

然后访问验证:

image.png

6.7 全局异常中间件-提取出全局错误处理问题

1
2
3
4
5
6
7
8
css复制代码app := fiber.New(fiber.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"code": 500,
"msg": err.Error()},
)
},
})

3.总结


以上仅仅是个人结合官网做的一系列的实践总结梳理,如有笔误!欢迎批评指正!感谢各位大佬!

码字不易,要不你点个赞呗 哈哈!

结尾

END

简书:www.jianshu.com/u/d6960089b…

掘金:juejin.cn/user/296393…

公众号:微信搜【小儿来一壶枸杞酒泡茶】

小钟同学 | 文 【欢迎一起学习交流】| QQ:308711822

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%