登录必须用bcrypt.CompareHashAndPassword校验哈希,禁用明文比对;数据库密码字段需为TEXT或VARCHAR(255);状态管理须用session或JWT,禁用ctx.Locals跨请求存用户信息。

登录接口不校验哈希、注册不查重、路由写错路径却返回 200——这些不是“逻辑没写完”,而是 Fiber 项目上线前最常被忽略的硬伤。
登录必须用 bcrypt.CompareHashAndPassword,别碰明文比对
前端传 "password": "123456",数据库存的是 "$2a$12$..." 这种哈希值。直接 == 或 strings.EqualFold 比对,永远失败。
-
CompareHashAndPassword第二个参数必须是[]byte(pwd),不是string;传错类型会 panic - 密码字段在数据库里必须是
TEXT或VARCHAR(255),VARCHAR(32)会截断哈希导致校验失败 - 别在
ctx.Locals存用户 ID 当“登录态”——它只活到当前请求结束,下一次请求就丢了 - 真要维持状态,用
github.com/gofiber/fiber/v2/middleware/session(配 Redis)或 JWT(签发后放Authorization: Bearer xxx)
注册接口必须查重 + 哈希 + 事务保护
两个用户同时注册同个邮箱,只靠 “先 SELECT 再 INSERT” 会漏掉竞态,最终插入两条重复记录。
- 数据库建唯一索引:
CREATE UNIQUE INDEX idx_users_email ON users(email)(PostgreSQL)或等效语句 - 用 GORM 插入时捕获冲突错误:
if errors.Is(err, gorm.ErrDuplicatedKey)或具体驱动错误(如pg.ErrUniqueViolation) - 密码必须走
bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost),别手写盐、别用 MD5 -
ctx.BodyParser(&req)后立刻做空值检查:if req.Email == "" || req.Password == "",否则空字符串进库也算“成功注册”
app.Get("/users", ...) 和 app.Get("/users/", ...) 是两条不同路由
Fiber 默认 StrictRouting: true,这意味着 /users 和 /users/ 不互通。你只注册了前者,访问后者就是 404 —— 而且不会重定向,前端收不到任何提示。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 别全局关掉
StrictRouting,否则/users/:id可能错误匹配/users/123里的123为id,而/users/却被当成/users/:id的一部分 - 正确做法:要么显式注册两个路由,要么加中间件统一跳转:
c.Redirect(c.Path()[:len(c.Path())-1], 301)(仅当末尾是/时) - API 文档里必须写死是否带尾斜杠,前端调用不能靠“试试看”
- Group 分层时,
api := app.Group("/api")后注册api.Get("/users", ...),路径实际是/api/users,不是/users
BodyParser 不等于数据校验,空字段和非法格式得自己拦
ctx.BodyParser(&v) 只负责把 JSON 映射成 struct 字段,它不管字段是否为空、长度是否超限、邮箱格式对不对。
- 结构体字段必须首字母大写 + 正确
json:"email"tag,否则解析后全是零值 - 关键字段解析后必须手动检查:
if !isValidEmail(v.Email) { c.Status(400).Send("invalid email") } - 更稳的方式是加
validate:"required,email,min=6,max=254"tag,配合validator.New().Struct(v) - 别在
BodyParser后再调c.Body()—— Fasthttp 的 body 是单次读取流,第二次返回空字节
真正卡住上线的,往往不是“功能没实现”,而是 SELECT FOR UPDATE 忘加、JWT 签名密钥硬编码在代码里、或者 app.Listen() 的 error 被忽略导致服务根本没起来。这些点不写进日志、不跑集成测试,上线后只能靠用户报错才发现。

















