系列文章
:Go 聊天室实战系列(1/6)

项目地址https://gitee.com/gaogaohang/go-land_-learning

技术栈:Go 1.23 + Gin + PostgreSQL + Redis + Vue3


一、为什么选择 Go?

在开始这个项目之前,我对比了几个技术选型:

方案

优点

缺点

Java + Spring Boot

生态成熟、文档丰富

启动慢、内存占用高

Node.js + Express

开发快、异步友好

类型安全弱、CPU 密集型弱

Go + Gin

性能好、并发强、部署简单

生态相对年轻

最终选择 Go 的理由:

  1. 性能:聊天室需要处理大量并发连接

  2. 部署:单个二进制文件,无需 JVM

  3. 学习价值:补充多语言能力


二、项目架构设计

2.1 分层架构

采用经典的三层架构:

┌─────────────────────────────────────────┐
│              API Layer                   │
│    (internal/api/)                       │
│    - 路由定义                            │
│    - 请求参数绑定                         │
│    - 响应格式化                          │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│           Service Layer                  │
│    (internal/service/)                   │
│    - 业务逻辑                            │
│    - 事务管理                            │
│    - 权限校验                            │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│          Repository Layer                │
│    (internal/repository/)                │
│    - 数据库操作                          │
│    - GORM 封装                           │
│    - 缓存管理                            │
└─────────────────────────────────────────┘

2.2 目录结构

go-chat/
├── cmd/                      # 命令入口
├── internal/                 # 内部包(Go 私有包约定)
│   ├── api/                  # API 层
│   │   ├── auth.go          # 认证接口
│   │   ├── user.go          # 用户接口
│   │   └── chat.go          # 聊天接口
│   ├── service/              # 业务层
│   │   ├── auth_service.go
│   │   ├── user_service.go
│   │   └── chat_service.go
│   ├── repository/           # 数据层
│   │   ├── user_repo.go
│   │   └── message_repo.go
│   ├── model/                # 数据模型
│   │   ├── user.go
│   │   └── message.go
│   ├── middleware/           # 中间件
│   │   ├── jwt.go           # JWT 认证
│   │   └── cors.go          # CORS
│   └── config/               # 配置管理
├── pkg/                      # 公共包
│   ├── response/             # 统一响应
│   ├── errors/               # 错误码定义
│   └── logger/               # 日志模块
├── web/                      # 前端代码 (Vue3 + TS)
├── config.dev.yaml           # 开发环境配置
├── config.test.yaml          # 测试环境配置
├── config.prod.yaml          # 生产环境配置
├── main.go                   # 入口文件
├── Makefile                  # 构建脚本
├── .air.toml                 # air 热重载配置
└── README.md                 # 项目文档

设计原则

  • internal/:Go 的私有包约定,外部无法 import

  • pkg/:公共包,可被外部引用

  • 配置文件按环境分离


三、核心代码解析

3.1 入口文件 (main.go)

func main() {
    // 1. 加载配置
    config.LoadConfig()
    
    // 2. 初始化日志
    logger.Init()
    
    // 3. 初始化数据库
    database.InitPostgres()
    database.InitRedis()
    
    // 4. 注册路由
    router := gin.Default()
    api.RegisterRoutes(router)
    
    // 5. 启动服务
    port := config.GetServerPort()
    router.Run(":" + port)
}

启动流程:配置 → 日志 → 数据库 → 路由 → 服务

3.2 统一响应格式 (pkg/response/)

type Response struct {
    Code      int         `json:"code"`
    Message   string      `json:"message"`
    Data      interface{} `json:"data"`
    RequestID string      `json:"request_id"`
}
​
func Success(data interface{}) Response {
    return Response{
        Code:      0,
        Message:   "success",
        Data:      data,
        RequestID: generateRequestID(),
    }
}
​
func Error(code int, message string) Response {
    return Response{
        Code:      code,
        Message:   message,
        Data:      nil,
        RequestID: generateRequestID(),
    }
}

设计思考

  • 所有接口返回统一格式

  • code=0 表示成功,非 0 表示错误

  • request_id 用于日志追踪

3.3 错误码定义 (pkg/errors/)

// 系统级错误 (1000-1999)
const (
    ErrSystemError = 1000 + iota
    ErrDatabaseError
    ErrCacheError
)
​
// 认证授权 (2000-2999)
const (
    ErrAuthRequired = 2000 + iota
    ErrTokenExpired
    ErrTokenInvalid
)
​
// 用户模块 (3000-3999)
const (
    ErrUserNotFound = 3000 + iota
    ErrUserExists
)
​
// ... 好友、会话、消息、群组模块

分类清晰,便于前端根据错误码处理。


四、配置管理

4.1 多环境配置

# config.dev.yaml
server:
  port: 8080
  mode: debug
​
database:
  host: localhost
  port: 5432
  user: 111111
  password: 111111
  db_name: chatdb
​
redis:
  host: localhost
  port: 6379
​
log:
  level: debug
  output: stdout

4.2 环境变量覆盖

export CHAT_ENV=prod
export CHAT_SERVER_PORT=9090
./bin/go-chat

优先级:环境变量 > 配置文件 > 默认值


五、Makefile 自动化

.PHONY: build run test clean
​
# 构建
build:
    go build -o bin/go-chat main.go
​
# 开发环境运行
run:
    go run main.go -env=dev
​
# 生产环境运行
run-prod:
    ./bin/go-chat -env=prod
​
# 测试
test:
    go test -v ./...
​
# 测试覆盖率
test-coverage:
    go test -coverprofile=coverage.out ./...
    go tool cover -html=coverage.out
​
# Docker 构建
docker-build:
    docker build -t go-chat:latest .
​
# Docker 运行
docker-run:
    docker run -p 8080:8080 go-chat:latest
​
# 开发模式(热重载)
dev:
    air

使用体验

make build      # 构建
make run        # 运行
make test       # 测试
make dev        # 热重载开发

六、开发工具链

6.1 air 热重载

# .air.toml
root = "."
tmp_dir = "tmp"
​
[build]
cmd = "go build -o ./tmp/main main.go"
bin = "./tmp/main"
include_ext = ["go", "yaml", "json"]
exclude_dir = ["tmp", "web", "bin"]

效果:修改代码后自动重启服务,无需手动操作。

6.2 项目统计

指标

数值

提交次数

53 次

开发周期

约 2 周

代码行数

约 3000 行

语言分布

Go 52.1%, Vue 36.9%, TS 9.6%


八、遇到的挑战

挑战 1:分层边界模糊

问题:Service 层和 Repository 层职责不清 解决:明确约定

  • Repository:只负责 CRUD,不包含业务逻辑

  • Service:处理业务规则、事务、权限

挑战 2:配置管理混乱

问题:多处读取配置,难以统一管理 解决:单例配置中心,启动时加载,全局访问

挑战 3:错误处理不一致

问题:有的返回 error,有的返回 Response 解决:统一使用 pkg/response 包装


九、下一步

在下一篇文章中,我们将深入讲解 JWT 认证与中间件设计,包括:

  • JWT 原理详解

  • 登录接口实现

  • 认证中间件编写

  • 权限校验实践


十、项目信息

📦 项目地址https://gitee.com/gaogaohang/go-land_-learning

📝 系列文章:Go 聊天室实战系列(1/6)

🏷️ 技术标签:#Go #Gin #PostgreSQL #Redis #Vue3


欢迎 Star & Fork!有任何问题欢迎在评论区交流! 🚀