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:
-H "Content-Type: application/json" \
-d '{"name":"李四","email":"lisi@qq.com","role":"student"}'
curl http:
curl -X PUT http:
-H "Content-Type: application/json" \
-d '{"role":"admin"}'
curl -X DELETE http:
预期输出
- 所有请求自动打印日志:
[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
go run main.go
预期效果
- 页面显示温度/湿度卡片 + 实时折线图
- 数据每 2 秒自动刷新
- 多开浏览器窗口,所有窗口同步收到推送
- 关闭窗口后服务端日志打印断开信息