Go 1.27 · 零 Web 框架 · 零 ORM

把企业级 Go 服务的常用部分,一次性固化下来

matex 不做全家桶。它只固化最常用的布局与基础设施入口——标准库 net/http + 薄封装,配了才建、不配就不存在——再把这套约定交给 AI 与 skills 去生成代码。

25pkg/core 基础设施包
19可离线运行的示例
14AI skill
0第三方路由 / ORM 依赖
bash
# 1. 零依赖起步:只要 configs/config.min.yaml(http + log + 服务段)
make run-min

curl -i localhost:8080/healthz
curl -i localhost:8080/api/v1/hello/world

# 2. 带数据库、仍然零外部依赖(纯 Go SQLite,无 cgo、无 Docker)
make migrate DRIVER=sqlite DSN=file:matex.db
make run-sqlite

# 3. 要真依赖时
make dev                     # postgres / mysql / redis / memcache / kafka
make migrate DSN=postgres://matex:matex@localhost:5432/matex?sslmode=disable
make run

一个部署单元,四行代码

服务 = Name() + Setup() + BuildRouter()。 verticle.Run 负责其余全部:加载配置、初始化基础设施、启动 HTTP、 处理信号、优雅退出。

go
type Service interface {
    Name() string                              // 配置段 key、日志与指标前缀
    Setup(ctx context.Context, env *Env) error // 解码服务段、装配 domain
    BuildRouter(s *httpx.Server) error         // 注册路由
}

func main() {
    if err := verticle.Run(context.Background(), &app.DemoService{}); err != nil {
        log.Fatal(err)
    }
}

基础设施句柄对业务是私有的,一律经 Env 访问器读取:RequireDB() 在未配置时让启动失败,DB() 用逗号-ok 判可用。业务代码里不会出现 if env.DB != nil 这种话。

  • 业务代码不 import 驱动库 pgx、go-redis、franz-go、gin… 全部收在 pkg/core/* 之后, 由 golangci-lint 的 depguard 强制,不靠自觉。
  • Handler 不碰 ResponseWriter 签名统一 func(ctx, *http.Request) (any, error):返回 nil 即 204,返回 errs.* 即对应状态码 + {code,msg,data}。
  • 配了才建,不配就不存在 只有 http: 段的最小配置也能起服务;db / redis / kafka / tracing / auth 随加随用,未配置时是 no-op,不为它们付任何代价。
  • 测试不需要 Docker 纯 Go SQLite、miniredis、kfake、进程内 gRPC·rpcx——make ci 跑的就是全部示例。

请求走一趟,发生了什么

一次请求要经过的每一层都是显式的:中间件槽、超时、trace id、错误映射、指标。 下图的每一步在 架构总览 里都有对应代码。

sequenceDiagram
    autonumber
    participant C as 客户端
    participant G as guard
(panic 恢复 · 体积限制 · 安全头) participant W as wrap
(trace id · 超时 · 封套) participant M as 中间件
(认证 · 限流 · 幂等) participant H as Handler
(ctx, *http.Request) (any, error) C->>G: GET /api/v1/hello/world G->>W: 放行 W->>W: 开 server span,定 X-Request-ID W->>M: 带 trace id 与超时的 ctx M->>H: ctx + 请求 H-->>M: (data, nil) 或 (nil, errs.*) M-->>W: 结果 W->>W: 渲染 {code,msg,data} · 记日志与指标 W-->>C: 200 或 4xx/5xx
trace id 的优先级是「调用方给的 X-Request-ID → 当前 trace id → 新生成」, 并回写到响应头,客户端不用接链路后端也能做关联。

能力按需接入,语义写进 skill

每项能力都有:一个可离线跑的示例、一个教 AI 怎么接的 skill、以及一节说明取舍的文档。 三者指向同一份代码。

看全部 20 个示例 →

代码生成交给 AI,不交给 CLI

生成器是「会过时的约定」,skill 是「给 AI 的约定」。仓库里的 AGENTS.md 加一组 skill 就是生成器,而且随代码一起演进。

bash
npx skills add smallnest/matex --all   # 一次装齐 15 个 skill

# 之后直接说人话:
#   "新增一个订单业务域"
#   "接 postgres,加 Redis 缓存,配 gRPC"
#   "给支付接口加幂等和限流"

取舍写在明面上

不做什么,和做什么一样重要。

舍弃 理由
ORM SQL 直写 + 泛型扫描已够;ORM 增加黑盒与逃逸面。
gin / echo / chi Go 1.22 ServeMux 已支持方法路由与路径参数,再引第三方路由只会增加依赖面。
服务发现 / 注册中心 归 K8s 与网关;静态 DNS + 环境变量足够。
默认开启的重治理 限流、熔断、幂等、追踪都有薄封装,但一律 opt-in。

完整取舍与理由 →