Files
oci-portal/.trellis/spec/backend/directory-structure.md
T

2.1 KiB

后端目录结构

Go 后端工程(oci-portal/)的目录职责与代码组织约定。

目录职责

oci-portal/
├── go.mod              模块名 oci-portal,依赖 oracle/oci-go-sdk/v65
├── go.sum
├── cmd/
│   └── server/         启动入口 main.go
└── internal/
    ├── api/            HTTP 路由、参数绑定、响应、中间件
    ├── config/         环境变量读取
    ├── crypto/         敏感字段 AES-GCM 加解密
    ├── database/       SQLite 连接和 AutoMigrate
    ├── model/          GORM 数据模型
    ├── oci/            OCI SDK 封装,真实云请求只出现在此包
    └── service/        业务逻辑和本地快照同步

已实现:API Key 导入(ini 原文或显式字段)、测活(Identity GetTenancy)、账户类别判定(Organizations CLOUDCM 订阅)、重新测活时的快照差异同步。

代码组织约定

  • 布局遵循官方约定:入口在 cmd/<binary>/main.go,非导出实现放 internal/(出现对外复用库时才建 pkg/),不过度分层。
  • 接口定义在使用方包中;先有第二个实现或测试替身需求,再抽接口。
  • 用 guard clause 尽早 return,减少嵌套。
  • defer 紧跟资源获取语句,成对管理释放。
  • 结构体初始化写字段名;已知容量的 slice/map 用 make(T, 0, n) 预分配。
  • 注释解释"为什么"而非"是什么";导出符号写以名字开头的 godoc 注释。
  • 路由参数:资源 id 可能含 / 等 URL 保留字符时(如 OCI PAR id),一律经 query 传递而非路径参数 —— gin 路径段不匹配 %2F,会直接 404(2026-07 round6 教训)。
  • OSP Gateway(账单/发票,internal/oci/billing.go):服务只在租户主区域提供,每个请求都带 ospHomeRegion 且客户端 SetRegion 到主区域 —— 主区域公共名经测活 HomeRegionKey + RegionByKey 解析,勿用凭据 region 直连;SDK 金额是 *float32,输出前经 money() 四舍五入抹掉 float64 转换噪音;PayInvoiceEmail 是 API 必填(付款回执),service 层校验后透传。