feat(lyra): 搭建基础骨架与配置响应组件
- 使用 Viper 加载 TOML 配置 - 定义统一响应、业务错误码及响应辅助函数 - 添加分层职责约束并同步架构文档
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# api 包
|
||||
|
||||
- 定义 HTTP 请求/响应 DTO,按资源分文件。
|
||||
- DTO 与内部模型分开:即使初期字段相近,也不把数据库模型直接暴露为响应,由 handler 层完成显式转换。
|
||||
- 不引用 handler、service、model,也不依赖 Gin,避免传输契约与实现耦合或循环引用。
|
||||
@@ -0,0 +1,21 @@
|
||||
package api
|
||||
|
||||
// ErrCode 错误码,前3位数表示错误类型,后3位数表示具体错误
|
||||
type ErrorCode int
|
||||
|
||||
const (
|
||||
CodeInvalidArgument ErrorCode = 10001
|
||||
CodeInternalError ErrorCode = 10002
|
||||
CodeLinkNotFound ErrorCode = 10003
|
||||
)
|
||||
|
||||
func (e ErrorCode) Message() string {
|
||||
switch e {
|
||||
case CodeInvalidArgument:
|
||||
return "请求参数不正确"
|
||||
case CodeLinkNotFound:
|
||||
return "链接不存在"
|
||||
default:
|
||||
return "服务暂时不可用"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package api
|
||||
|
||||
type Response struct {
|
||||
Success bool `json:"success"`
|
||||
Data any `json:"data,omitempty"`
|
||||
Error *ErrorInfo `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type ErrorInfo struct {
|
||||
Code ErrorCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Debug string `json:"debug,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# config 包
|
||||
|
||||
- 负责配置定义与加载。
|
||||
- 具体配置项、来源与加载方式随实际需求确定,由程序入口调用配置加载逻辑。
|
||||
@@ -0,0 +1,39 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
App AppConfig `mapstructure:"app"`
|
||||
HTTP HTTPConfig `mapstructure:"http"`
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Env string `mapstructure:"env"`
|
||||
}
|
||||
|
||||
type HTTPConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
v := viper.New()
|
||||
// 指定文件,按 .toml 扩展名识别格式
|
||||
v.SetConfigFile(path)
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("读取配置失败: %w", err)
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
return nil, fmt.Errorf("解析配置失败: %w", err)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# handler 包
|
||||
|
||||
- 负责参数绑定、API DTO 与内部模型的相互转换、响应输出。
|
||||
- 引用 internal/api 的 DTO,使用 Gin 完成绑定与响应。
|
||||
- 调用 service 时传递标准 context.Context,不下传 gin.Context。
|
||||
@@ -0,0 +1,4 @@
|
||||
# httpx 包
|
||||
|
||||
- 提供公共 HTTP 响应辅助。
|
||||
- 出现实际复用需求时再补充具体辅助函数,不预先设计无使用场景的抽象。
|
||||
@@ -0,0 +1,27 @@
|
||||
package httpx
|
||||
|
||||
import (
|
||||
"lyra/internal/api"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// OK 成功响应
|
||||
func OK(c *gin.Context, data any) {
|
||||
c.JSON(http.StatusOK, api.Response{
|
||||
Success: true,
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
// Fail 错误响应
|
||||
func Fail(c *gin.Context, status int, code api.ErrorCode, message string) {
|
||||
if message == "" {
|
||||
message = code.Message()
|
||||
}
|
||||
c.JSON(status, api.Response{
|
||||
Success: false,
|
||||
Error: &api.ErrorInfo{Code: code, Message: message},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# model 包
|
||||
|
||||
- 承载数据结构定义与数据访问:使用 Squirrel/SQL 构造查询、sqlx 执行与映射结果,驱动为 pgx stdlib。
|
||||
- SQL 与查询逻辑显式写在这一层,不使用 ORM 自动持久化。
|
||||
- 支持在 service 传入的同一事务内执行操作。
|
||||
- 使用标准 context.Context,不依赖 Gin,也不依赖 internal/api 的 DTO。
|
||||
@@ -0,0 +1,4 @@
|
||||
# postgres 包
|
||||
|
||||
- 负责建立与管理 PostgreSQL 连接,使用 pgx stdlib 驱动。
|
||||
- 连接参数来自 internal/config,连接供 model 层通过 sqlx 执行查询使用。
|
||||
@@ -0,0 +1,5 @@
|
||||
# router 包
|
||||
|
||||
- 负责路由注册与项目路径前缀,例如 `/api/polaris`。
|
||||
- Gin 的路由与请求处理逻辑留在 HTTP 层;service 和 model 不依赖 Gin。
|
||||
- 路由随资源实现逐步补充,不按业务项目建立代码子目录。
|
||||
@@ -0,0 +1,5 @@
|
||||
# service 包
|
||||
|
||||
- 承载业务规则与事务协调,通过 model 完成数据访问。
|
||||
- 需要原子性时,在同一事务内协调多次写入,不把各自独立提交的多次写入当成原子业务。
|
||||
- 使用标准 context.Context,不依赖 Gin,也不依赖 internal/api 的 DTO。
|
||||
Reference in New Issue
Block a user