Fiber

技术栈
后端框架
fibergolangweb框架fasthttp高性能Express风格

概览

Fiber 技术栈概览

Fiber 是基于 Fasthttp(Go 最快的 HTTP 引擎)构建的 Express 风格 Web 框架,由 Fenny 和 Fiber 社区维护。它刻意模仿 Express 的 API 设计,让 Node.js 开发者能无缝迁移到 Go 的高性能世界。

解决什么问题

  • Express 用户转 Go:API 高度相似,学习成本接近零
  • 极致吞吐量:基于 fasthttp,压测性能是 Gin 的 2 倍、Express 的 10 倍+
  • 低内存占用:适合资源受限环境或高密度部署
  • 快速原型:路由分组、中间件、模板引擎一应俱全

关键特性

  • Express 风格 API(app.Get、app.Use、ctx.JSON)
  • 底层使用 fasthttp,请求处理零内存分配
  • 内置限流、缓存、压缩、WebSocket 等中间件
  • 模板支持:HTML、Pug、Handlebars 等
  • Mounter 支持类似 Express.Router 的子应用

安装

环境准备

  • 操作系统:Windows 10+ / macOS 12+ / Ubuntu 20.04+
  • 运行时版本:Go 1.18+(推荐 1.22+)
  • 依赖项:git

安装命令

# 1. 创建并进入项目
mkdir my-fiber-app &;& cd my-fiber-app

# 2. 初始化 Go Module
go mod init my-fiber-app

# 3. 安装 Fiber v3(最新)
go get github.com/gofiber/fiber/v3

# 4. 创建 main.go(见例程)并运行
go run main.go

# 5. 编译部署
go build -o server
./server    # 默认监听 :3000

国内加速

go env -w GOPROXY=https://goproxy.cn,direct
go get github.com/gofiber/fiber/v3

可选中间件

go get github.com/gofiber/fiber/v3/middleware/cors
go get github.com/gofiber/fiber/v3/middleware/logger
go get github.com/gofiber/fiber/v3/middleware/limiter

常见安装问题

问题 解决方案
go get 版本冲突 Fiber v2 vs v3 API 不同,确认 import 路径含 /v3go mod tidy 清理
fasthttp 编译错误 fasthttp 依赖 C 标准库较少,纯 Go 可 CGO_ENABLED=0 go build
启动后无日志输出 Fiber 默认不打印请求日志,需手动 app.Use(logger.New())
端口被占 修改 app.Listen(":8080") 换端口

示例

Fiber 快速入门 — 用户管理 API

目标

使用 Fiber 的 Express 风格 API 快速搭建用户 CRUD,演示路由、中间件、参数解析。

完整代码

package main

import (
	"log"
	"strconv"
	"time"

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

type User struct {
	ID        int       `json:"id"`
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	Role      string    `json:"role"`
	CreatedAt time.Time `json:"createdAt"`
}

var (
	users  = []User{}
	nextID = 1
)

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

	// 全局日志中间件
	app.Use(func(c fiber.Ctx) error {
		start := time.Now()
		err := c.Next()
		log.Printf("[%s] %s — %v", c.Method(), c.Path(), time.Since(start))
		return err
	})

	// 用户路由组
	api := app.Group("/api")

	api.Get("/users", func(c fiber.Ctx) error {
		return c.JSON(fiber.Map{"count": len(users), "data": users})
	})

	api.Get("/users/:id", func(c fiber.Ctx) error {
		id, _ := strconv.Atoi(c.Params("id"))
		for _, u := range users {
			if u.ID == id {
				return c.JSON(u)
			}
		}
		return c.Status(404).JSON(fiber.Map{"error": "用户不存在"})
	})

	api.Post("/users", func(c fiber.Ctx) error {
		user := new(User)
		if err := c.Bind().JSON(user); err != nil {
			return c.Status(400).JSON(fiber.Map{"error": "JSON 解析失败"})
		}
		if user.Name == "" || user.Email == "" {
			return c.Status(400).JSON(fiber.Map{"error": "姓名和邮箱为必填"})
		}
		user.ID = nextID
		nextID++
		user.CreatedAt = time.Now()
		users = append(users, *user)
		return c.Status(201).JSON(user)
	})

	api.Put("/users/:id", func(c fiber.Ctx) error {
		id, _ := strconv.Atoi(c.Params("id"))
		for i, u := range users {
			if u.ID == id {
				var update User
				if err := c.Bind().JSON(&update); err != nil {
					return c.Status(400).JSON(fiber.Map{"error": "JSON 解析失败"})
				}
				if update.Name != "" {
					users[i].Name = update.Name
				}
				if update.Email != "" {
					users[i].Email = update.Email
				}
				if update.Role != "" {
					users[i].Role = update.Role
				}
				return c.JSON(users[i])
			}
		}
		return c.Status(404).JSON(fiber.Map{"error": "用户不存在"})
	})

	api.Delete("/users/:id", func(c fiber.Ctx) error {
		id, _ := strconv.Atoi(c.Params("id"))
		for i, u := range users {
			if u.ID == id {
				users = append(users[:i], users[i+1:]...)
				return c.JSON(fiber.Map{"message": "已删除"})
			}
		}
		return c.Status(404).JSON(fiber.Map{"error": "用户不存在"})
	})

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

运行步骤

go mod init fiber-demo
go get github.com/gofiber/fiber/v3
go run main.go

测试

# 新增
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"李四","email":"lisi@qq.com","role":"student"}'

# 获取
curl http://localhost:3000/api/users

# 更新
curl -X PUT http://localhost:3000/api/users/1 \
  -H "Content-Type: application/json" \
  -d '{"role":"admin"}'

# 删除
curl -X DELETE http://localhost:3000/api/users/1

预期输出

  • 所有请求自动打印日志:[GET] /api/users — 1.2ms
  • Fiber v3 使用 c.Bind().JSON() 替代旧版 c.BodyParser()
  • 响应头自动带 Server: Fiber

Fiber WebSocket 实时数据推送

目标

使用 Fiber WebSocket 实现服务端定时推送模拟传感器数据(温度/湿度),前端实时折线图展示——典型 IoT/毕设看板场景。

后端代码

package main

import (
	"encoding/json"
	"log"
	"math/rand"
	"sync"
	"time"

	"github.com/gofiber/fiber/v3"
	"github.com/gofiber/contrib/websocket"
)

type SensorData struct {
	Timestamp   int64   `json:"timestamp"`
	Temperature float64 `json:"temperature"`
	Humidity    float64 `json:"humidity"`
}

var (
	clients   = make(map[*websocket.Conn]bool)
	clientsMu sync.RWMutex
)

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

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

	app.Get("/ws", websocket.New(func(c *websocket.Conn) {
		clientsMu.Lock()
		clients[c] = true
		clientsMu.Unlock()
		log.Printf("客户端连接,在线: %d", len(clients))

		for {
			_, _, err := c.ReadMessage()
			if err != nil {
				break
			}
		}

		clientsMu.Lock()
		delete(clients, c)
		clientsMu.Unlock()
		log.Printf("客户端断开,在线: %d", len(clients))
	}))

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

func broadcastLoop() {
	ticker := time.NewTicker(2 * time.Second)
	defer ticker.Stop()

	for range ticker.C {
		data := SensorData{
			Timestamp:   time.Now().UnixMilli(),
			Temperature: 20 + rand.Float64()*15,
			Humidity:    40 + rand.Float64()*40,
		}
		payload, _ := json.Marshal(data)

		clientsMu.RLock()
		for client := range clients {
			client.WriteMessage(websocket.TextMessage, payload)
		}
		clientsMu.RUnlock()
	}
}

前端页面 (public/index.html)

用 Chart.js 绘制温度/湿度双轴折线图,每 2 秒追加数据点,保留最近 30 个点滚动展示。

关键 JS 逻辑:

  • const ws = new WebSocket('ws://' + location.host + '/ws')
  • ws.onmessage 接收 JSON 更新 Chart.js 数据和卡片数值
  • 双 Y 轴:左侧温度(°C),右侧湿度(%)

运行步骤

go mod init sensor-dashboard
go get github.com/gofiber/fiber/v3
go get github.com/gofiber/contrib/websocket
mkdir public
# 将 HTML 保存为 public/index.html
go run main.go
# 访问 http://localhost:3000

预期效果

  • 页面显示温度/湿度卡片 + 实时折线图
  • 数据每 2 秒自动刷新
  • 多开浏览器窗口,所有窗口同步收到推送
  • 关闭窗口后服务端日志打印断开信息

教程

Fiber 毕设实战 — Express 用户迁移到 Go 的最短路径

前言

Fiber 是 Go 生态中长得最像 Express 的框架。如果你熟悉 JavaScript/Express,Fiber 能让你在几小时内上手 Go 后端开发,同时享受 Go 的极致性能。

第一章:Fiber 与 Express 的对应关系

Express Fiber
const app = express() app := fiber.New()
app.use(middleware) app.Use(middleware)
app.get('/path', handler) app.Get("/path", handler)
req.params.id c.Params("id")
req.query.q c.Query("q")
req.body c.Body()
res.json(obj) c.JSON(obj)
res.status(404).send() c.Status(404).SendString("")
next() c.Next()

API 几乎一一对应,迁移成本极低。

第二章:Fiber 的 Context 方法大全

func handler(c fiber.Ctx) error {
    // 获取路径参数
    id := c.Params("id")

    // 获取查询参数
    page := c.Query("page", "1")

    // 获取请求头
    token := c.Get("Authorization")

    // 解析 JSON Body
    var body map[string]any
    c.Bind().JSON(&body)

    // 解析 Form
    name := c.FormValue("name")

    // 返回 JSON
    return c.JSON(fiber.Map{
        "id":   id,
        "page": page,
    })

    // 返回文件
    // return c.SendFile("./report.pdf")

    // 重定向
    // return c.Redirect("/new-url", 301)
}

第三章:Fiber 的钩子(Hooks)

Fiber v3 引入了钩子系统,可以在请求生命周期的特定阶段执行逻辑:

app := fiber.New()

// Hooks
app.Hooks().OnListen(func(listenData fiber.ListenData) error {
    log.Printf("🚀 服务已启动在 %s", listenData.Addr)
    return nil
})

app.Hooks().OnRoute(func(route fiber.Route) error {
    log.Printf("📝 注册路由: %s %s", route.Method, route.Path)
    return nil
})

第四章:Fiber + GORM 实战

type Product struct {
    ID    uint    `gorm:"primaryKey" json:"id"`
    Name  string  `json:"name"`
    Price float64 `json:"price"`
    Stock int     `json:"stock"`
}

func main() {
    db, _ := gorm.Open(sqlite.Open("shop.db"), &gorm.Config{})
    db.AutoMigrate(&Product{})

    app := fiber.New()

    app.Get("/products", func(c fiber.Ctx) error {
        var products []Product
        db.Find(&products)
        return c.JSON(products)
    })

    app.Post("/products", func(c fiber.Ctx) error {
        var p Product
        c.Bind().JSON(&p)
        db.Create(&p)
        return c.Status(201).JSON(p)
    })

    app.Listen(":3000")
}

第五章:Fiber 性能调优

app := fiber.New(fiber.Config{
    // 提高并发
    Prefork:       true,   // 多进程模式
    CaseSensitive: true,   // 路由区分大小写
    StrictRouting: false,  // /foo 和 /foo/ 视为相同

    // 压缩
    EnableTrustedProxyCheck: true,

    // 限制请求体大小(防攻击)
    BodyLimit: 10 * 1024 * 1024, // 10MB
})

Prefork: true 会让 Fiber fork 多个子进程(数量等于 CPU 核心数),每个子进程独立监听同一端口(SO_REUSEPORT),性能接近 Nginx。

思考题

  1. Fiber 的 Prefork 模式与 Node.js PM2 Cluster 有什么区别?
  2. Fiber 基于 fasthttp,而 fasthttp 不兼容 net/http 接口,这带来什么利弊?
  3. 在什么场景下应该选择 Fiber 而不是 Gin?