# 沒實作的六件事：從框架學到什麼

> gortex 刻意沒做的六件事：完整 graceful shutdown、middleware 錯誤語意、組態熱更新、請求級 timeout、結構化錯誤、OpenAPI 產生，每件都難在生產級細節。

原文：https://sheng.page/posts/gortex-what-we-didnt-build/ · 發布：2026-06-14 · 作者：Sheng

這篇收尾盤點 gortex 六個未實作方向，以及從整個框架能學到什麼。

## 六個未實作方向

gortex 的設計文件自己列了六個「值得做但沒做」的方向。共通點是：看起來只差一步，實際每個都卡在生產級細節。

1. **完整的 graceful shutdown 流程**：〈[WebSocket Hub：Go 版 Actor 模型](/posts/gortex-websocket-actor-hub/)〉的 hub 已有基本的 graceful shutdown，但生產級還要 drain（先從 LB 摘除：K8s preStop + readiness 切 false，等 in-flight 請求跑完）、關閉順序（HTTP listener → drain → WS Hub → DB pool）、以及把 OS signal 的 deadline 一路傳到各子系統。
2. **middleware chain 的錯誤語意**：現在 middleware 回 `error` 由 `ServeHTTP` 統一處理。生產框架還要分「可重試 vs 不可重試」、「該記 log vs 已自行處理」，以及 error boundary，某層吞掉 error 後，上層還觀測得到嗎。
3. **組態熱更新**：`pkg/config` 目前一次性載入。K8s 的 ConfigMap 會被更新到掛載目錄，若用 `fsnotify` 監聽，就能不重啟調 log level、改 rate limit 閾值、切 feature flag。
4. **請求級 timeout propagation**：目前沒有「全域請求超時」。生產框架通常在最外層 middleware 設一個 deadline context，確保 handler 忘了設 timeout、整條請求也不會無限掛住（〈[可觀測性：三態健康檢查與 tracing 抽象層](/posts/gortex-observability-health-tracing/)〉的 per-check timeout 是局部版的同一招）。
5. **結構化錯誤**：`pkg/errors` 現在是簡單的 code→message 註冊表。更進階的會有 error code 命名空間、error chain、i18n：

```go
// 現在：扁平的 code → message
// 想要的：命名空間 + 可分層判斷
err := errors.New("ORDER.PAYMENT_FAILED", ...)
if errors.Is(err, order.ErrPayment) { /* 分層處理 */ }
```

6. **OpenAPI / Swagger 自動產生**：`core/app/doc/` 已有 `swagger.Provider` 骨架，但 spec 產生還沒完成。從 struct tag + 方法簽章自動推 OpenAPI，正好是〈[Struct tag 宣告式路由：reflect 實戰](/posts/gortex-struct-tag-routing/)〉的延伸。

## 從框架學到什麼

把整個系列倒過來看，會浮出幾條反覆出現的原則：

- **答案要看情境**：kitchen-sink 在微服務是過度設計，在平台團隊是治理工具（〈[為什麼造一個 kitchen-sink 框架](/posts/gortex-why-kitchen-sink-framework/)〉）。沒有放諸四海皆準的架構。
- **成本一次付清**：reflect 掃路由、建樹都在啟動期，hot path 零分配、零反射（從路由到零分配那幾篇，見〈[Segment-trie 路由器：不靠正則的匹配](/posts/gortex-segment-trie-router/)〉與〈[零分配的秘密：Context pool 與 smartParams](/posts/gortex-zero-allocation-context/)〉）。把貴的操作擠到開機那一刻。
- **看資料是什麼樣子來選工具**：高頻計數用 atomic、分片鎖（〈[併發計數與韌性：sharded metrics 與 circuit breaker](/posts/gortex-metrics-and-circuit-breaker/)〉）；獨佔狀態的事件流用 channel（WebSocket Hub 那篇）。別反射性套 channel，也別什麼都上鎖。
- **對介面寫程式**：tracing 換 OTel、health check 換實作，都不動業務碼（可觀測性那篇、〈[interface 與組合](/posts/go-interfaces-and-composition/)〉）。
- **失敗要大聲、輸入要設限**：未知 middleware、未實作的 rbac / inject 啟動就炸（struct tag 路由那篇）；body、JWT、rate limit 都在邊界設限（〈[安全中介層全家桶：CORS / CSRF / JWT / rate limit / binder](/posts/gortex-security-middleware-suite/)〉）。
- **直說極限**：`LogResponseBody` 是 no-op、`inject` 只解析不注入、`rbac` 沒實作，說清楚比假裝全能好。

## 收尾

gortex 不是要跟 Gin、Echo 競爭的開源框架，是一份 reference implementation，研究與紀錄用途，不為 production。它的價值有兩面：一是把「平台框架要做哪些決策」列出來示範（kitchen-sink 那篇的起點），二是這份「沒做的六件事」本身，就是一張地圖，標出生產級基礎設施真正難的地方。

知道什麼該做、什麼刻意不做、為什麼不做，這是讀框架原始碼比較能帶走的東西。


## 補充筆記

- 六個未實作方向（完整 graceful shutdown、middleware 錯誤語意、config 熱更新、請求級 timeout、結構化錯誤、OpenAPI 自動產生）每個都卡在生產級細節。
- 系列主軸：答案看情境、成本一次付清、按資料性質選工具、對介面寫程式、失敗大聲 + 輸入設限、直說極限。
- gortex 是 reference implementation，價值在示範決策與刻意留白，不是 production 框架。
- 「沒做的事」清單本身，就是一張生產級基礎設施的難點地圖。
- 讀框架最值得帶走的：知道什麼該做、什麼刻意不做、以及為什麼。

原始碼：[yshengliao/gortex](https://github.com/yshengliao/gortex)。

---

> 想法與技術判斷出自 Sheng，和 Claude 一起起草 · 環境 Go 1.25（gortex go.mod）· 本系列為事後回填整理 · 列入 20260613 blog 翻新計劃，新漆未乾。