Skip to content

Repository files navigation

Currency Forum

Currency Forum 是一个基于 Go 构建的汇率资讯社区后端项目。系统围绕“币种对讨论”这一垂直场景展开,支持用户注册登录、文章发布与查询、汇率录入与查询、文章点赞等核心功能。

项目不是单纯的 CRUD Demo,而是把认证、分层架构、MySQL 持久化、Redis 缓存、事务一致性、分页筛选、健康检查、优雅停机、Docker Compose 和 Swagger 文档等后端工程能力组合到一个完整的小型服务中。

项目亮点

  • 基于 Gin 设计 RESTful API,完成用户、文章、汇率、点赞等核心业务模块。
  • 采用 Controller-Service-Repository 三层架构拆分接口层、业务层和数据访问层。
  • 使用 GORM + MySQL 完成用户、文章、汇率、点赞关系等数据建模,并支持服务启动阶段自动迁移。
  • 基于 JWT + Gin Middleware 实现登录鉴权,通过路由分组区分公开接口和受保护接口。
  • 引入 Redis 缓存文章点赞总数,并结合数据库回源机制提升热点点赞数据读取性能。
  • 设计点赞关系表,通过 article_id + user_id 联合唯一索引防止重复点赞。
  • 点赞流程使用事务保证点赞关系写入与文章点赞数更新的一致性。
  • 支持文章和汇率列表分页、筛选、排序查询,满足前端多条件列表展示需求。
  • 提供健康检查、请求 ID、访问日志、优雅停机等基础服务治理能力。
  • 提供 Dockerfiledocker-compose.yml 和 OpenAPI/Swagger 文档,方便本地启动和接口调试。

技术栈

分类 技术
语言 Go
Web 框架 Gin
ORM GORM
数据库 MySQL
缓存 Redis
配置管理 Viper
认证 JWT, bcrypt
接口文档 OpenAPI 3.0, Swagger UI
部署 Docker, Docker Compose
测试 Go test

系统架构

flowchart TD
    Client["Client / Web Page"] --> Router["Gin Router"]
    Router --> Middleware["Middleware"]
    Middleware --> Controller["Controller"]
    Controller --> Service["Service"]
    Service --> Repository["Repository"]
    Repository --> MySQL["MySQL"]
    Service --> Redis["Redis"]
Loading

分层说明

层级 职责
Controller 接收 HTTP 请求,参数绑定与校验,返回统一响应
Service 处理业务规则、事务边界、跨组件协作
Repository 封装数据库查询、分页、筛选、排序等数据访问逻辑
Model 定义用户、文章、汇率、点赞关系等数据模型
Middleware 处理鉴权、请求 ID、访问日志、异常恢复等通用逻辑

核心业务模块

用户认证

  • 用户注册
  • 用户登录
  • 密码使用 bcrypt 加密存储
  • 登录成功后返回 JWT
  • 受保护接口通过 Authorization: Bearer <token> 访问

文章系统

  • 发布文章
  • 查询文章详情
  • 查询文章列表
  • 支持分页查询
  • 支持按关键词、作者、币种对筛选
  • 支持按最新、最热、最早排序

文章会绑定币种对,例如 USD/CNY,使内容和汇率场景产生业务关联,而不是普通的帖子系统。

汇率系统

  • 新增汇率记录
  • 查询汇率列表
  • 支持按币种对筛选
  • 支持按数据来源筛选
  • 支持 latestOnly 查询每个币种对的最新一条记录
  • 保留 sourcecapturedAt 字段,方便后续扩展第三方汇率源和定时同步

点赞系统

点赞模块不是简单地对文章表字段做自增,而是采用:

  • article_likes 表保存真实点赞关系
  • articles.likes_count 保存聚合后的点赞数
  • Redis 缓存文章点赞总数

这样可以同时满足:

  • 防止同一用户重复点赞
  • 保留用户点赞关系,方便后续扩展取消点赞、点赞记录等功能
  • 使用事务保证点赞关系和点赞数更新一致
  • 使用 Redis 降低热点点赞数读取压力

点赞流程

sequenceDiagram
    participant C as Client
    participant M as Auth Middleware
    participant S as Like Service
    participant DB as MySQL
    participant R as Redis

    C->>M: POST /api/articles/{id}/like
    M->>M: Parse JWT
    M->>S: Pass username and article id
    S->>DB: Check article and user
    S->>DB: Check article_likes relation
    alt Not liked
        S->>DB: Insert like relation in transaction
        S->>DB: Increment article likes_count
    else Already liked
        S->>S: Skip write
    end
    S->>DB: Count likes by article id
    S->>R: Refresh like count cache
    S-->>C: Return like result
Loading

数据模型

erDiagram
    USERS ||--o{ ARTICLES : writes
    USERS ||--o{ ARTICLE_LIKES : likes
    ARTICLES ||--o{ ARTICLE_LIKES : receives

    USERS {
        uint id
        string username
        string password
    }

    ARTICLES {
        uint id
        string title
        string preview
        string content
        string base_currency
        string quote_currency
        string status
        int likes_count
        uint author_id
    }

    ARTICLE_LIKES {
        uint id
        uint article_id
        uint user_id
    }

    EXCHANGE_RATES {
        uint id
        string base_currency
        string quote_currency
        decimal rate
        string source
        datetime captured_at
    }
Loading

目录结构

.
├── config                 # 配置加载、MySQL/Redis 初始化、数据迁移、资源关闭
│   └── global             # 全局数据库和 Redis 客户端
├── controller             # HTTP 控制层
│   └── middlewares        # 鉴权、请求 ID、访问日志等中间件
├── docs                   # OpenAPI 文档和 Swagger UI 页面
├── models                 # GORM 数据模型
├── repository             # 数据访问层
├── router                 # 路由注册
├── service                # 业务逻辑层
├── utils                  # JWT、密码加密等工具函数
├── web                    # 简单演示页面
├── Dockerfile             # 应用镜像构建文件
├── docker-compose.yml     # app + MySQL + Redis 编排
├── main.go                # 服务入口
└── README.md

快速启动

使用 Docker Compose 启动

推荐使用 Docker Compose 一键启动应用、MySQL 和 Redis:

docker compose up --build

启动后访问:

地址 说明
http://localhost:3000/ 演示页面
http://localhost:3000/docs Swagger API 文档
http://localhost:3000/openapi.yaml OpenAPI 原始文件
http://localhost:3000/healthz 健康检查

本地启动

如果不使用 Docker,需要先准备:

  • Go
  • MySQL
  • Redis

修改 config/config.yml 中的数据库和 Redis 配置后执行:

go run main.go

默认服务地址:

http://localhost:3000

配置说明

默认配置文件位于 config/config.yml

app:
  name: CurrencyExchangeApp
  port: 3000

database:
  dsn: "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"

redis:
  addr: "127.0.0.1:6379"

jwt:
  secret: "interview-demo-secret"
  expireHours: 72

项目支持通过环境变量覆盖配置,例如:

APP_PORT=3000
DATABASE_DSN="root:123456@tcp(mysql:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
REDIS_ADDR="redis:6379"
JWT_SECRET="interview-demo-secret"

API 概览

认证接口

方法 路径 说明 鉴权
POST /api/auth/register 用户注册
POST /api/auth/login 用户登录

文章接口

方法 路径 说明 鉴权
GET /api/articles 查询文章列表
GET /api/articles/{id} 查询文章详情
POST /api/articles 发布文章
GET /api/articles/{id}/like 查询文章点赞数
POST /api/articles/{id}/like 点赞文章

汇率接口

方法 路径 说明 鉴权
GET /api/exchangeRates 查询汇率列表
POST /api/exchangeRates 新增汇率记录

健康检查

方法 路径 说明
GET /healthz 检查服务、MySQL、Redis 状态

完整接口参数请查看 Swagger 文档:

http://localhost:3000/docs

示例请求

注册

curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username":"demo_user","password":"demo123456"}'

登录

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"demo_user","password":"demo123456"}'

发布文章

curl -X POST http://localhost:3000/api/articles \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "title": "USD/CNY short term view",
    "preview": "A short note about USD/CNY movement.",
    "content": "USD/CNY remains sensitive to policy signals and market liquidity.",
    "baseCurrency": "USD",
    "quoteCurrency": "CNY",
    "status": "published"
  }'

新增汇率

curl -X POST http://localhost:3000/api/exchangeRates \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "baseCurrency": "USD",
    "quoteCurrency": "CNY",
    "rate": 7.2301,
    "source": "manual"
  }'

测试

执行全部测试:

go test ./...

如果本机 Go 构建缓存目录存在权限问题,可以临时指定项目内缓存目录:

GOCACHE=.gocache go test ./...

当前测试主要覆盖:

  • JWT 生成与解析
  • 密码加密与校验
  • 分页参数规范化
  • 请求 ID 中间件

工程化能力

  • 配置文件和环境变量结合
  • 服务启动阶段自动迁移数据表
  • MySQL 和 Redis 连接初始化
  • 请求 ID 中间件
  • 访问日志中间件
  • JWT 鉴权中间件
  • 健康检查接口
  • HTTP 服务优雅停机
  • Docker Compose 一键启动
  • Swagger API 文档

后续优化方向

  • 接入第三方汇率 API,增加定时同步任务
  • 增加评论、收藏、热门币种榜等社区功能
  • 增加 refresh token 和登出黑名单机制
  • 增加角色权限控制
  • 增加数据库和 Redis 的集成测试
  • 对热点列表和汇率最新值查询做进一步索引优化

项目定位

这个项目适合作为 Go 后端面试项目展示。它的重点不是业务模块数量,而是围绕一个垂直场景,把认证、缓存、事务、分层、分页、迁移、服务治理和容器化部署等常见后端能力串成一个可运行、可讲清楚、可继续扩展的小型系统。

About

基于 Go + Gin + GORM + MySQL + Redis 的汇率资讯社区后端项目,支持用户认证、文章发布、汇率查询、点赞缓存、Docker 部署和 Swagger 文档。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages