feat: 添加服务和数据库初始化
This commit is contained in:
321
README.md
Normal file
321
README.md
Normal 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
|
||||
Reference in New Issue
Block a user