又一个goweb框架——fiber框架

go-fiber 主要定位为一个轻量级、高性能的 Web 框架

由于fiber使用 fasthttp 作为 HTTP 引擎,使得 Fiber 的性能非常出色

学习fiber的大部分人,应该是有gin做基础的吧?如果是零基础学fiber的,可以反馈给我,人多的话

出一期fiber的零基础入门课程

本课程是针对有gin基础的人,但是处于其他原因需要使用fib 做开发

fiber怎么用

运行项目

运行是通过Listen方法

package main

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

func main() {
  app := fiber.New(fiber.Config{})
  app.Get("/", func(c *fiber.Ctx) error {
    return nil
  })
  app.Post("/", func(c *fiber.Ctx) error {
    return nil
  })
  app.Put("/", func(c *fiber.Ctx) error {
    return nil
  })
  app.Delete("/", func(c *fiber.Ctx) error {
    return nil
  })
  err := app.Listen(":80")
  fmt.Println(err)
}

响应

响应字符串

c.SendString("string")

响应json

c.JSON(map[string]any{"code": 0, "msg": "成功"})
type Info struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
}
c.JSON(Info{"fengfeng", 18})

响应html

c.Set("Content-Type", "text/html;charset=utf-8")
c.SendString("<h1>你好</h1>")
c.SendFile("index.html")

静态路由

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

路由分组

Route

Group

app.Route("/system", func(router fiber.Router) {
router.Get("health", func(c *fiber.Ctx) error { return c.SendString("system.health") })
router.Get("info", func(c *fiber.Ctx) error { return c.SendString("system.info") })
router.Get("user/list", func(c *fiber.Ctx) error { return c.SendString("system.user/list") })
})

group := app.Group("/video")
group.Get("info", func(c *fiber.Ctx) error { return c.SendString("video.info") })
group.Get("progress", func(c *fiber.Ctx) error { return c.SendString("video.progress") })

动态路由

除了动态路由,fiber还支持*通配符路由

app.Get("/user/:name", func(c *fiber.Ctx) error {
    return c.SendString("动态路由" + c.Params("name"))
  })
app.Get("/user/*", func(c *fiber.Ctx) error {
  return c.SendString("通配符路由")
})

反向解析

在定义路由的时候,可以给路由设置一个名字

在其他地方,就可以基于这个路由名称反向得到路由的路径

// 1. 给路由命名
app.Get("/user/:id", func(c *fiber.Ctx) error {
    return c.SendString("用户ID:" + c.Params("id"))
}).Name("user.detail") // 命名为 user.detail

// 2. 反向解析 URL(动态生成 /user/123)
app.Get("/test", func(c *fiber.Ctx) error {
    // 传入路由名 + 参数映射,生成 URL
    url, err := c.GetRouteURL("user.detail", fiber.Map{"id": 123})
    if err != nil {
        return err
    }
    return c.SendString("用户详情页 URL:" + url) // 输出:/user/123
})

文件上传

SaveFile不会自动创建目录

package main

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

func main() {
  app := fiber.New(fiber.Config{})
  app.Post("upload", func(c *fiber.Ctx) error {
    fileHeader, err := c.FormFile("file")
    if err != nil {
      return err
    }
    fmt.Println(fileHeader.Filename)
    return c.SaveFile(fileHeader, "uploads/"+fileHeader.Filename)
  })
  app.Post("uploads", func(c *fiber.Ctx) error {
    form, err := c.MultipartForm()
    if err != nil {
      return err
    }
    for s, headers := range form.File {
      for _, header := range headers {
        fmt.Printf("%s %s\n", s, header.Filename)
      }
    }
    return c.Status(201).SendString("成功")
  })
  app.Listen(":80")
}

参数绑定

绑定json,绑定form

都是用BodyParser,通过请求的ContentType进行区分的

如果是json,就用json的tag

如果是form,就用form的tag

type RequestData struct {
  Name string `json:"name" form:"name"`
  Age  int    `json:"age" form:"age"`
}
var user RequestData
err := c.BodyParser(&user)

绑定query

type RequestData struct {
  Name string `query:"name"`
  Age  int    `query:"age"`
}
var user RequestData
err := c.QueryParser(&user)

绑定uri

要和动态路由结合

app.Get("/user/:name/:id", func(c *fiber.Ctx) error {
  type RequestData struct {
    Name string `params:"name"`
    ID   int    `params:"id"`
  }
  var user RequestData
  c.ParamsParser(&user)
  return c.JSON(user)
})

参数校验

和gin用的同一个参数校验库,不过使用逻辑有点不太一样

gin是直接把validate库内置了,但是fiber需要手动操作

go get github.com/go-playground/validator/v10
package main

import (
  "fmt"
  "github.com/go-playground/validator/v10"
  "github.com/gofiber/fiber/v2"
)

func main() {
  app := fiber.New(fiber.Config{})
  validate := validator.New()

  app.Get("/validate", func(c *fiber.Ctx) error {
    type RequestData struct {
      Name  string `json:"name" params:"name" validate:"required,min=2,max=10"` // 必须存在,长度2-10
      ID    int    `json:"id" params:"id" validate:"required,min=1"`            //  必须存在,最小值1
      Email string `json:"email" params:"email" validate:"email"`               //  存在就得是合法的邮箱格式
    }
    var user RequestData
    err := c.QueryParser(&user)
    if err != nil {
      fmt.Println("参数绑定失败", err)
      return err
    }
    err = validate.Struct(user)
    if err != nil {
      fmt.Println("参数校验失败", err)
      return err
    }
    return c.JSON(user)
  })
  err := app.Listen(":80")
  fmt.Println(err)
}

校验错误显示中文
  1. 创建翻译器
  2. 给validate 注册翻译器
  3. 遇到校验错误使用翻译器
package main

import (
  "fmt"
  "github.com/go-playground/locales/zh"
  ut "github.com/go-playground/universal-translator"
  "github.com/go-playground/validator/v10"
  zh_translations "github.com/go-playground/validator/v10/translations/zh"
  "github.com/gofiber/fiber/v2"
  "strings"
)

var trans ut.Translator
var validate *validator.Validate

func init() {
  // 创建翻译器
  uni := ut.New(zh.New())
  trans, _ = uni.GetTranslator("zh")

  // 初始化 validator 并注册中文翻译
  validate = validator.New()
  if err := zh_translations.RegisterDefaultTranslations(validate, trans); err != nil {
    panic(fmt.Sprintf("注册中文翻译失败:%v", err))
  }
}

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

  app.Get("/validate", func(c *fiber.Ctx) error {
    type RequestData struct {
      Name  string `json:"name" params:"name" validate:"required,min=2,max=10"` // 必须存在,长度2-10
      ID    int    `json:"id" params:"id" validate:"required,min=1"`            //  必须存在,最小值1
      Email string `json:"email" params:"email" validate:"email"`               //  存在就得是合法的邮箱格式
    }
    var user RequestData
    err := c.QueryParser(&user)
    if err != nil {
      fmt.Println("参数绑定失败", err)
      return err
    }
    err = validate.Struct(user)
    if err != nil {
      //fmt.Println("参数校验失败", err)
      errs := err.(validator.ValidationErrors)
      var errMsgs []string
      for _, e := range errs {
        // 使用翻译器
        errMsgs = append(errMsgs, e.Translate(trans))
      }
      return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
        "error": strings.Join(errMsgs, ";"),
      })
    }
    return c.JSON(user)
  })
  err := app.Listen(":80")
  fmt.Println(err)
}

请求头响应头操作

// 1. 获取请求头
app.Get("/header", func(c *fiber.Ctx) error {
    token := c.Get("Authorization") // 获取 Authorization 头
    userAgent := c.Get("User-Agent")// 获取 User-Agent
    return c.JSON(fiber.Map{
        "token":      token,
        "user_agent": userAgent,
    })
})

// 2. 设置响应头
app.Get("/set-header", func(c *fiber.Ctx) error {
    c.Set("Content-Type", "application/json;charset=utf-8") // 显式设置响应头
    c.Set("Cache-Control", "max-age=3600") // 设置缓存时间(1小时)
    return c.JSON(fiber.Map{"msg": "已设置响应头"})
})

中间件

在中间件里面可以很方便的获取请求体和响应体的数据

视图中间件
package main

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

func AuthMiddleware(c *fiber.Ctx) error {
  fmt.Println("请求前")
  fmt.Println("请求体数据:", string(c.Body()))
  // return c.JSON(map[string]any{"code": -1}) // 如果需要拦截
  c.Next()
  fmt.Println("响应后")
  fmt.Println("响应体数据:", string(c.Response().Body()))
  return nil
}

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

  app.Post("/user", AuthMiddleware, func(c *fiber.Ctx) error {
    fmt.Println("视图函数")
    return c.JSON(map[string]any{"data": "用户数据"})
  })
  err := app.Listen(":80")
  fmt.Println(err)
}

分组中间件

可以通过group的后续参数挂载中间件

也可以基于group的对象的use方法挂载中间件,两者是等价的

app.Group("/", LoggerMiddleware).Use(LoggerMiddleware)
全局中间件

直接基于app的use方法挂载中间件即可

这个中间件会对所有路由生效(包括静态路由),并且优先级最高

func LoggerMiddleware(c *fiber.Ctx) error {
  // 请求前:记录开始时间
  start := time.Now()

  // 放行请求(执行后续中间件和路由处理函数)
  err := c.Next()

  // 响应后:计算耗时并打印日志
  duration := time.Since(start)
  fmt.Printf("[%s] %s %s - %v\n",
    c.Method(), // 请求方法(GET/POST 等)
    c.Path(),   // 请求路径
    c.IP(),     // 客户端 IP
    duration,   // 处理耗时
  )
  return err
}

app.Use(LoggerMiddleware)

中间件之间的参数传递

举个例子:每次在视图里面做参数绑定和校验 都挺麻烦的,是否可以在中间件里面做参数绑定和参数校验,然后在视图函数中获取校验之后的数据

package main

import (
  "github.com/go-playground/validator/v10"
  "github.com/gofiber/fiber/v2"
)

var validate1 *validator.Validate

func init() {
  validate1 = validator.New()
}
func bindMiddleware[T any](c *fiber.Ctx) error {
  var cr T
  err := c.QueryParser(&cr)
  if err != nil {
    return err
  }
  err = validate1.Struct(cr)
  if err != nil {
    return err
  }
  c.Locals("value", cr)
  c.Next()
  return nil
}

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

  type Info struct {
    Name string `query:"name"`
  }

  app.Get("/", bindMiddleware[Info], func(c *fiber.Ctx) error {
    info := c.Locals("value").(Info)
    return c.JSON(info)
  })

  app.Listen(":80")
}

官方支持中间件

中间件名称包路径核心用途
CORS 跨域github.com/gofiber/cors/v2处理跨域请求,支持配置允许的源、方法、请求头,解决前端跨域问题。
限流github.com/gofiber/limiter/v2限制接口请求频率(如每秒 / 每分钟最大请求数),防止接口被刷,保护服务稳定。
JWT 认证github.com/gofiber/jwt/v3基于 JWT(JSON Web Token)的身份认证,用于用户登录态校验、接口权限控制。
WebSocketgithub.com/gofiber/websocket/v2快速实现 WebSocket 服务,自动处理 HTTP 到 WebSocket 的协议升级,简化双向通信。
静态资源内置(无需额外安装)通过 app.Static() 提供静态文件服务,支持压缩、目录浏览、缓存等高级配置(核心功能,虽未单独拆包,但属于官方核心能力)。
请求 IDgithub.com/gofiber/requestid/v2为每个请求生成唯一 ID(如 UUID),并写入响应头(X-Request-ID),方便日志追踪、链路排查。
日志github.com/gofiber/fiber/v2/middleware/logger内置日志中间件,记录请求方法、路径、耗时、状态码等信息,支持自定义日志格式(如 JSON 格式)。
恢复(Panic 捕获)github.com/gofiber/fiber/v2/middleware/recover内置异常捕获中间件,捕获请求处理中的 panic,防止服务崩溃,返回友好的 500 错误响应。
压缩github.com/gofiber/compression/v2自动压缩响应内容(支持 gzip、brotli 等算法),减少传输带宽,提升接口响应速度(尤其适合文本类响应,如 JSON、HTML)。
ETaggithub.com/gofiber/etag/v2自动生成响应的 ETag(资源标识),支持客户端缓存(相同资源第二次请求返回 304 Not Modified),减少重复传输。
cors中间件
package main

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

func main() {
  app := fiber.New()
  // 注册 CORS 中间件
  app.Use(cors.New(cors.Config{
    AllowOrigins:     "https://example.com,http://localhost:3000", // 允许的前端域名
    AllowMethods:     "GET,POST,PUT,DELETE,PATCH",                 // 允许的请求方法
    AllowHeaders:     "Content-Type,Authorization",                // 允许的请求头
    ExposeHeaders:    "Content-Length",                            // 允许前端读取的响应头
    AllowCredentials: true,                                        // 允许携带 Cookie
  }))

  app.Get("/api/data", func(c *fiber.Ctx) error {
    return c.JSON(fiber.Map{"data": "跨域请求成功"})
  })
  app.Listen(":80")
}

jwt中间件
  1. 通过颁发jwt的接口,生成jwt
  2. 后续请求需要认证的接口,把jwt带上,在统一的中间件中进行认证
package main

import (
  "github.com/gofiber/fiber/v2"
  "github.com/gofiber/jwt/v3"
  "github.com/golang-jwt/jwt/v4"
  "time"
)

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

  // 公开接口(无需认证):登录生成 Token
  app.Post("/login", func(c *fiber.Ctx) error {
    // 模拟登录成功,生成 JWT Token
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
      "username": "test",
      "exp":      jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), // 24小时过期
    })
    tokenString, _ := token.SignedString([]byte("your-secret-key")) // 密钥(生产环境需保密)
    return c.JSON(fiber.Map{"token": tokenString})
  })

  // 受保护接口:注册 JWT 中间件
  app.Use(jwtware.New(jwtware.Config{
    SigningKey: []byte("your-secret-key"),
  }))

  // 需认证的接口(只有携带有效 Token 才能访问)
  app.Get("/api/user", func(c *fiber.Ctx) error {
    // 从中间件中获取解析后的 Token 信息
    user := c.Locals("user").(*jwt.Token)
    claims := user.Claims.(jwt.MapClaims)
    return c.JSON(fiber.Map{"username": claims["username"]})
  })

  app.Listen(":80")
}

限流中间件
package main

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

func GetIp(c *fiber.Ctx) string {
  return c.IP()
}

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

  // 注册限流中间件
  app.Use(limiter.New(limiter.Config{
    KeyGenerator: GetIp,           // 按 IP 限流(也可按用户 ID 等自定义)
    Expiration:   5 * time.Second, // 限流窗口时间
    Max:          1,               // 窗口内最大请求数
    // 超过限流时的响应
    LimitReached: func(c *fiber.Ctx) error {
      return c.Status(fiber.StatusTooManyRequests).JSON(fiber.Map{
        "code": 429,
        "msg":  "请求过于频繁,请稍后再试",
      })
    },
  }))

  app.Get("/api/limit", func(c *fiber.Ctx) error {
    return c.SendString("限流接口请求成功")
  })
  app.Listen(":80")
}

websocket支持

在 Fiber 中实现 WebSocket 路由需要借助官方的 websocket 中间件,该中间件会升级 HTTP 连接为 WebSocket 连接并处理握手逻辑

go get github.com/gofiber/websocket/v2
package main

import (
  "log"

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

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

  // 普通 HTTP 路由(用于测试)
  app.Get("/", func(c *fiber.Ctx) error {
    return c.SendString("请通过 WebSocket 连接 ws://localhost:80/ws")
  })

  // WebSocket 路由:使用 websocket.New 中间件包装处理函数
  app.Get("/ws", websocket.New(func(c *websocket.Conn) {
    // 连接成功后打印客户端信息
    log.Printf("新的 WebSocket 连接:%s", c.RemoteAddr())
    defer log.Printf("WebSocket 连接关闭:%s", c.RemoteAddr())

    // 循环读取客户端消息
    for {
      // 读取消息类型(text/binary)和内容
      msgType, msg, err := c.ReadMessage()
      if err != nil {
        log.Printf("读取消息失败:%v", err)
        break // 退出循环,关闭连接
      }

      // 打印收到的消息
      log.Printf("收到来自 %s 的消息:%s", c.RemoteAddr(), string(msg))

      // 向客户端回声(原样返回消息)
      if err := c.WriteMessage(msgType, msg); err != nil {
        log.Printf("发送消息失败:%v", err)
        break
      }
    }
  }))

  // 启动服务
  log.Fatal(app.Listen(":80"))
}



fiber怎么配置

静态文件配置项

app.Static("/static", "./public", fiber.Static{
    Compress:  true,  // 启用静态文件压缩(节省带宽,适合 JS/CSS/HTML)
    Browse:    true,  // 启用目录浏览(访问 /static 时显示文件列表,类似 Nginx)
    Index:     "home.html", // 自定义索引文件(默认是 index.html)
    MaxAge:    86400, // 客户端缓存时间(1天,单位秒)
})

fiber项目配置

app := fiber.New(fiber.Config{
    Prefork:       true,         // 启用多核(利用 CPU 多核心,提升性能)
    CaseSensitive: true,         // 路由大小写敏感(如 /User 和 /user 视为不同路由)
    StrictRouting: true,         // 严格路由(如 /user/ 和 /user 视为不同路由)
    AppName:       "MyFiberApp", // 应用名称 可以在视图的 c.App().Config().AppName获取到
    ErrorHandler: func(c *fiber.Ctx, err error) error { // 全局错误处理
      return c.Status(500).JSON(fiber.Map{
        "code": 500,
        "msg":  "服务器内部错误:" + err.Error(),
      })
    },
})

和gin的区别?

功能点GinFiber
性能引擎基于 net/http基于 fasthttp(性能更高)
全局配置配置项少(需手动扩展)fiber.Config 内置多核、错误处理等(更灵活)
路由反向解析需第三方库(如 gin-contrib/cors内置 Name() + GetRouteURL()(更方便)
静态文件配置仅基础功能(无压缩 / 目录浏览)支持压缩、目录浏览、自定义索引(更强大)
文件上传需手动处理 multipart.Form内置 FormFile() + SaveFile()(更简洁)
WebSocket需第三方库(如 gorilla/websocket官方 websocket 中间件(开箱即用)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值