feat: 添加服务和数据库初始化

This commit is contained in:
2026-03-02 23:30:00 +08:00
parent 607ff9a055
commit 52cfe1b911
9 changed files with 1091 additions and 33 deletions

321
README.md Normal file
View File

@@ -0,0 +1,321 @@
# go-web-gin
一个基于 [Gin](https://github.com/gin-gonic/gin) 的 Go Web 应用脚手架,提供开箱即用的基础设施组件。
## 特性
- 🚀 **快速启动** - 简洁的 API 设计,快速搭建 Web 服务
- 🔧 **配置管理** - 支持 YAML 配置文件和环境变量覆盖
- 📝 **结构化日志** - 基于 [Zap](https://github.com/uber-go/zap) 的高性能日志
- 🗄️ **数据库支持** - MySQL (GORM) 和 Redis 单例连接
- 🌍 **多环境** - 支持 Local、Development、Production 环境
- 🧩 **单例模式** - 组件单例管理,避免重复初始化
## 安装
```bash
go get git.hujye.com/infrastructure/go-web-gin
```
## 快速开始
### 1. 创建配置文件
在项目根目录创建 `config/config.yml`
```yaml
server:
host: 0.0.0.0
port: 8080
mode: debug # debug, release, test
app:
name: my-app
environment: local
log_level: info
log:
output_to_file: true
filename: logs/app.log
max_size: 100
max_backups: 3
max_age: 28
compress: true
mysql:
host: 127.0.0.1
port: 3306
user: root
password: ""
db_name: test
charset: utf8mb4
parse_time: true
max_idle_conns: 10
max_open_conns: 100
conn_max_lifetime: 3600
redis:
addr: 127.0.0.1:6379
password: ""
db: 0
pool_size: 10
min_idle_conns: 5
max_retries: 3
dial_timeout: 5
read_timeout: 3
write_timeout: 3
```
### 2. 编写主程序
```go
package main
import (
"context"
go_web_gin "git.hujye.com/infrastructure/go-web-gin"
"github.com/gin-gonic/gin"
)
func main() {
// 创建应用实例
app := go_web_gin.New()
// 初始化数据库(可选)
app.InitMySQL()
app.InitRedis()
// 注册全局中间件
app.UseMiddleware(gin.Recovery())
// 注册路由
app.RegisterRoutes(func(e *gin.Engine) {
e.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
e.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
// 使用日志
app.Logger().Info(c.Request.Context(), "get user", "id", id)
c.JSON(200, gin.H{"user_id": id})
})
// 使用数据库
e.GET("/db-test", func(c *gin.Context) {
db := app.DB()
if db != nil {
// 执行数据库操作
c.JSON(200, gin.H{"db": "connected"})
} else {
c.JSON(500, gin.H{"error": "db not initialized"})
}
})
// 使用 Redis
e.GET("/redis-test", func(c *gin.Context) {
rdb := app.Redis()
if rdb != nil {
rdb.Set(c.Request.Context(), "test", "value", 0)
c.JSON(200, gin.H{"redis": "connected"})
} else {
c.JSON(500, gin.H{"error": "redis not initialized"})
}
})
})
// 启动服务
// 非生产环境可传入自定义地址,生产环境使用配置文件地址
app.Run()
}
```
## API 文档
### App 结构
```go
type App struct {
engine *gin.Engine
db *gorm.DB
rdb *redis.Client
logger *logger.Logger
}
```
### 方法列表
| 方法 | 说明 | 返回值 |
|------|------|--------|
| `New()` | 创建新的 App 实例 | `*App` |
| `UseMiddleware(...)` | 注册全局中间件 | - |
| `RegisterRoutes(func)` | 注册路由 | - |
| `InitMySQL()` | 初始化 MySQL 连接 | `*gorm.DB` |
| `InitRedis()` | 初始化 Redis 连接 | `*redis.Client` |
| `DB()` | 获取数据库实例 | `*gorm.DB` |
| `Redis()` | 获取 Redis 实例 | `*redis.Client` |
| `Logger()` | 获取日志实例 | `*logger.Logger` |
| `Run(addr ...string)` | 启动服务 | `error` |
### Run 方法行为
- **非生产环境**:优先使用传入的地址,否则使用配置文件地址
- **生产环境**:始终使用配置文件地址
```go
// 使用配置文件地址
app.Run()
// 非生产环境使用 :3000生产环境仍用配置文件地址
app.Run(":3000")
```
## 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `RUN_ENV` | 运行环境 (`LOCAL`, `DEVELOPMENT`, `PRODUCTION`) | `LOCAL` |
| `CFG_PATH` | 配置文件路径 | `config/config.yml` |
## 日志使用
```go
// 基本用法
app.Logger().Info(ctx, "message")
app.Logger().Error(ctx, "error message")
app.Logger().Warn(ctx, "warning message")
app.Logger().Debug(ctx, "debug message")
// 带键值对
app.Logger().Info(ctx, "user logged in", "user_id", "123", "ip", "192.168.1.1")
```
日志格式会根据环境自动切换:
- **Local**: Console 格式,便于阅读
- **Development/Production**: JSON 格式,便于日志收集
## 上下文用户信息
使用 `web` 包在上下文中传递用户信息:
```go
import "git.hujye.com/infrastructure/go-web-gin/web"
// 设置用户信息
ctx = web.SetUserID(ctx, "user-123")
ctx = web.SetUserName(ctx, "john")
ctx = web.SetTrace(ctx, "trace-456")
ctx = web.SetFromIP(ctx, "192.168.1.1")
// 获取用户信息
userID := web.GetUserID(ctx)
userName := web.GetUserName(ctx)
// 或一次性构建
userInfo := web.NewUserInfo().
WithUserID("user-123").
WithUserName("john").
WithTrace("trace-456").
WithFromIP("192.168.1.1")
ctx = web.ToContext(ctx, userInfo)
```
日志会自动从上下文中提取用户信息并记录。
## 使用 svr 包直接操作 Gin
如果需要直接使用 Gin 引擎单例:
```go
import "git.hujye.com/infrastructure/go-web-gin/svr"
// 获取引擎
engine := svr.GetEngine()
// 快捷方法
svr.Use(middleware...)
svr.GET("/ping", handler)
svr.POST("/users", handler)
svr.PUT("/users/:id", handler)
svr.DELETE("/users/:id", handler)
// 路由组
api := svr.Group("/api/v1")
api.GET("/users", handler)
// 启动服务
svr.Run(":8080")
```
## 配置读取
```go
import "git.hujye.com/infrastructure/go-web-gin/config"
// 获取完整配置
cfg := config.Get()
// 访问配置项
addr := cfg.GetAddr() // host:port
isDebug := cfg.IsDebug() // 是否 debug 模式
isRelease := cfg.IsRelease() // 是否 release 模式
// 动态读取配置(支持嵌套键)
dbHost := config.GetString("mysql.host")
dbPort := config.GetInt("mysql.port")
```
## 项目结构
```
go-web-gin/
├── app.go # 应用核心
├── app_test.go # 测试套件
├── config/
│ └── config.go # 配置管理
├── database/
│ ├── mysql.go # MySQL 单例
│ └── redis.go # Redis 单例
├── env/
│ └── env.go # 环境变量
├── logger/
│ ├── logger.go # 日志核心
│ ├── encoder.go # 编码器
│ └── struct.go # 结构定义
├── server/
│ └── server.go # 服务器封装
├── svr/
│ └── server.go # Gin 单例
└── web/
└── user.go # 上下文用户信息
```
## 运行测试
```bash
# 运行所有测试
go test -v ./...
# 运行特定测试套件
go test -v ./... -run TestAppRunSuite
```
## 依赖
- [gin-gonic/gin](https://github.com/gin-gonic/gin) - Web 框架
- [uber-go/zap](https://github.com/uber-go/zap) - 高性能日志
- [go-gorm/gorm](https://github.com/go-gorm/gorm) - ORM
- [redis/go-redis](https://github.com/redis/go-redis) - Redis 客户端
- [spf13/viper](https://github.com/spf13/viper) - 配置管理
- [stretchr/testify](https://github.com/stretchr/testify) - 测试框架
## License
MIT License
## Author
**hujye**
- Email: hujie@hujye.com