feat(backend): Go 服务骨架(配置、日志、数据库、中间件、Wire)

- config: Viper YAML 配置 + 环境变量覆盖
- logs: zap 结构化日志 + trace_id 链路追踪 + 敏感信息脱敏
- db: PostgreSQL (GORM) + Redis (go-redis) 连接管理
- middleware: Trace/Logger/CORS/Recovery 四层中间件
- provider: Wire 编译时依赖注入
- main.go: 优雅启动/关闭 HTTP 服务

Made-with: Cursor
This commit is contained in:
bujinyuan
2026-02-28 10:41:20 +08:00
parent d81c5743f5
commit c8ffbedf75
15 changed files with 906 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
// Package utils 提供通用工具函数
package utils
import (
"net/http"
"time"
"github.com/echochat/backend/pkg/logs"
"github.com/gin-gonic/gin"
)
// Response 统一 API 响应结构
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
TraceID string `json:"trace_id,omitempty"`
Time string `json:"time"`
}
// ResponseOK 成功响应 200
func ResponseOK(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, Response{
Code: 0,
Message: "success",
Data: data,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseCreated 创建成功响应 201
func ResponseCreated(c *gin.Context, data interface{}) {
c.JSON(http.StatusCreated, Response{
Code: 0,
Message: "created",
Data: data,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseBadRequest 参数错误响应 400
func ResponseBadRequest(c *gin.Context, message string) {
c.JSON(http.StatusBadRequest, Response{
Code: 400,
Message: message,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseUnauthorized 未认证响应 401
func ResponseUnauthorized(c *gin.Context, message string) {
c.JSON(http.StatusUnauthorized, Response{
Code: 401,
Message: message,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseForbidden 无权限响应 403
func ResponseForbidden(c *gin.Context, message string) {
c.JSON(http.StatusForbidden, Response{
Code: 403,
Message: message,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseNotFound 资源不存在响应 404
func ResponseNotFound(c *gin.Context, message string) {
c.JSON(http.StatusNotFound, Response{
Code: 404,
Message: message,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}
// ResponseError 服务器内部错误响应 500
func ResponseError(c *gin.Context, message string) {
c.JSON(http.StatusInternalServerError, Response{
Code: 500,
Message: message,
TraceID: logs.GetTraceID(c.Request.Context()),
Time: time.Now().Format("2006-01-02 15:04:05"),
})
}