bluebell 是一个由 Q1mi/bluebell 衍生并持续扩展的社区论坛项目。它保留了原项目“Gin + MySQL + Redis”的教学骨架,同时更新了前端页面、用户资料、帖子管理、搜索等更接近真实产品的能力。
当前仓库是一个前后端分离项目:
可前往cnb.cool平台fork仓库 点击云原生开发,在终端运行下面命令
docker compose up -d
启动后,在 PORTS 中添加 80 端口(如果使用 Docker Desktop),然后打开 Forwarded Address(如 https://zsh7nt5ioi-80.cnb.run/)即可体验论坛。
这个项目一方面适合作为 Go Web 后端学习样例,另一方面也在逐步向一个可运行的轻论坛产品靠近。
它重点覆盖的是这几类场景:
frontend (Vue 3 SPA)
|
v
Gin Router -> Controller -> Logic -> DAO(MySQL / Redis)
|
+-> MySQL: 用户、社区、帖子、草稿、搜索
|
+-> Redis: 排序、投票、社区帖子集合
routes/
middlewares/
controller/
logic/
dao/mysql/
dao/redis/
models/
frontend/src/views/
frontend/src/components/
frontend/src/composables/
frontend/src/api/
frontend/src/router/
项目通过 pkg/snowflake 封装 bwmarrin/snowflake,为用户 ID、帖子 ID 生成全局唯一业务主键。这样做的好处是业务层在写入数据库前就能拿到唯一 ID,不依赖 MySQL 自增列,也更适合后续扩展到分布式场景。
后端 Web 框架使用 Gin。项目通过 routes/routes.go 统一注册路由,通过 controller/ 处理请求,通过 middlewares/ 挂载 JWT 鉴权等公共逻辑。整体结构清晰,适合学习 Go Web 项目的基础分层。
项目使用 go.uber.org/zap 作为日志方案,并在 logger/ 中做了统一初始化与 Gin 日志接入。它主要用于:
相比标准库日志,Zap 更适合结构化日志输出,也更方便后续接入生产环境日志系统。
项目通过 settings/settings.go 使用 Viper 读取 settings/config.yaml,并把配置反序列化到全局 settings.GlobalConfig。当前配置内容包括:
这部分很适合初学者理解 Go 项目的“配置集中管理”方式。
项目已经接入 Swagger。接口注释写在 controller/ 层,通过 swag 生成文档数据,并通过 Gin 暴露 /swagger/index.html 页面,便于直接查看和调试 API。
项目通过 pkg/jwt 负责 token 生成与解析,通过 middlewares/auth.go 负责请求鉴权。用户登录成功后会拿到 JWT,前端在后续请求中通过 Authorization: Bearer <token> 传递身份信息。账号中心、发帖、编辑帖子、投票等接口都依赖这套机制。
项目已经通过 github.com/juju/ratelimit 接入全局令牌桶限流中间件。它在 routes.Setup() 中作为全局中间件挂载,所有进入 Gin 的请求都会先尝试从同一个令牌桶中取令牌。
当前限流参数来自 settings/config.yaml:
rate_limit.enabled:是否启用限流rate_limit.rate:每秒补充多少个令牌rate_limit.capacity:令牌桶最大容量当桶内没有令牌时,接口会返回 HTTP 429 Too Many Requests,响应体仍然保持项目统一格式,业务码为 CodeTooManyRequests。
项目使用 github.com/jmoiron/sqlx 操作 MySQL。sqlx 相比标准库 database/sql 更方便的地方在于:
当前用户、社区、帖子等核心数据都保存在 MySQL 中,对应代码主要在 dao/mysql/。
项目使用 github.com/redis/go-redis/v9 操作 Redis。Redis 在本项目里不负责正文存储,而主要负责:
这部分代码主要在 dao/redis/,尤其适合学习 zset、set、pipeline 等用法。
项目没有把所有数据都塞进一个存储里,而是做了明确分工:
这是本项目很值得学习的一个架构点:正文数据与排行榜数据分别落在最适合它们的存储里。
主页搜索目前接入增强帖子列表接口 /api/v1/posts2。搜索关键字会匹配公开帖子相关信息,主要用于首页内容流检索。
bluebell/
├── controller/ # HTTP 处理层
├── dao/
│ ├── mysql/ # MySQL 数据访问
│ └── redis/ # Redis 数据访问
├── docs/ # 项目文档
├── frontend/ # Vue 3 前端
├── logger/ # Zap 日志封装
├── logic/ # 业务逻辑层
├── middlewares/ # 中间件
├── models/ # 模型与建表 SQL
├── pkg/
│ ├── jwt/ # JWT 工具
│ └── snowflake/ # 雪花算法 ID
├── routes/ # 路由注册
├── settings/ # 配置读取
├── AGENT.md # 给 agent 的项目速览
└── README.md # 仓库说明
统一前缀:/api/v1
POST /signupPOST /loginGET /communityGET /community/:idGET /post/:idGET /postsGET /posts2GET /mePUT /mePOST /postPOST /post/draftGET /my/postsGET /my/posts/:idPUT /post/:idPUT /post/:id/draftPOST /post/:id/publishDELETE /post/:idPOST /vote使用下面的建表文件初始化数据库:
models/create_tables.sql项目会优先读取:
settings/config.yaml如果本地配置不存在,则回退到:
settings/config.example.yaml建议先复制示例配置,再按本地环境修改 MySQL、Redis、JWT 等参数。
go run ./
或:
make run
启动后可访问:
http://localhost:8080/swagger/index.htmlhttp://localhost:8080/api/v1/pingcd frontend
npm install
npm run dev
默认通过 Vite 启动本地开发服务。
项目提供了一套面向部署的 Docker Compose 编排,包含:
nginx:托管前端静态资源,并反向代理 /api/ 到后端。backend:运行 Go API 服务。mysql:保存用户、社区、帖子等持久化数据。redis:保存帖子排序、投票记录、社区帖子集合等数据。Docker 环境使用单独配置文件:
settings/config.docker.yaml该配置默认:
app.mode 设置为 releaseapp.enable_swagger 设置为 falseinfomysqlredis部署前必须修改:
settings/config.docker.yaml 中的 jwt.secretdocker-compose.yml 中的 MySQL 密码settings/config.docker.yaml 中对应的 MySQL 密码docker-compose.yml 中的 Redis --requirepasssettings/config.docker.yaml 中对应的 Redis 密码docker compose up -d --build
启动后访问:
http://localhost/http://localhost/api/v1/pingdocker compose ps
docker compose logs -f backend
docker compose logs -f nginx
docker compose down
如果需要连同 MySQL 和 Redis 数据一起删除:
docker compose down -v
注意:docker-compose.yml 会在 MySQL 首次初始化时执行 models/create_tables.sql 和 deploy/mysql/02_seed.sql。如果 mysql_data 数据卷已经存在,MySQL 官方镜像不会重复执行初始化 SQL。
如果你想快速读懂这个项目,推荐阅读顺序如下:
main.goroutes/routes.gocontroller/post.gologic/post.godao/mysql/post.godao/redis/vote.gofrontend/src/router/index.jsfrontend/src/views/Home.vuefrontend/src/views/Profile.vue后端常用校验命令:
go test ./...
前端常用校验命令:
cd frontend
npm run build