Skip to content
koopa0.dev
← the work

每一行程式碼都是未來的帳單:Go 工程師的成本意識

article· Jun 25, 2026· 5 min

Engineering 和 Hacking 的差距

寫程式碼很容易。決定「該不該寫這段程式碼」才是工程

我花了很長時間才意識到這件事。早期寫 Go 的時候,我的判斷標準是「能不能跑」和「夠不夠優雅」。後來維護過自己半年前寫的程式碼,我的判斷標準變了:這行程式碼,未來要由誰、在什麼時候、付多少代價來維護?

Engineering 和 Hacking 的差距不在技術能力,在於有沒有把成本算進去。

狀態 出發點 對成本的理解 結果
Hacking 現在能跑就好 忽略成本 埋雷,on-call 炸裂
Over-Engineering 展現技術、預測未來 誤判成本 無人能維護的精美廢物
Engineering 當下限制中的最優解 精準權衡 剛好夠用、易於重構

Over-Engineering 為什麼也是一種 Hacking?因為它沒有把複雜度本身當成成本。一個漂亮的抽象層,如果只有你一個人看得懂,就是負債而不是資產。


四種你每天都在付的成本

1. 認知負荷(Jump Tax)

每加一層 interface、每多一個抽象,讀程式碼的人就要多做一次心智跳轉。這個「跳轉稅」不是一次性的:它在每次閱讀、每次 debug、每次 onboarding 時反覆收取。

做決策的時候問自己:這個 interface 是為了現在的第二個實作,還是未來的幻想

如果答案是後者,刪掉它。等真正需要的時候再加,成本遠低於現在就維護一個沒人用的抽象。

2. 依賴與供應鏈

引入一個第三方套件很快。但你引入的不只是它的程式碼,還有它的 CVE、它的傳遞性依賴、它的維護者會不會棄坑。

Go 標準庫能做的事,就用標準庫。50 行自己寫的程式碼,比 3 年的依賴追蹤便宜太多了。

3. 資源與效能

anyreflect 給你靈活性,代價是 GC 壓力和型別安全延後到 runtime 才爆。

10% 的 GC overhead × 365 天 × N 台機器 = 真實的帳單。在小專案裡可以忽略,在生產環境裡不行。

4. 演進與相容性

直接暴露 struct 欄位很快、很簡單。但一旦有外部 package 在用,你就再也不能改欄位名、不能加驗證、不能加鎖。

現在省下的 5 分鐘,可能變成未來 3 個月的跨團隊協調。


Go 的設計本身就是成本決策

Go 語言的很多設計被批評「不夠先進」。沒有繼承、沒有泛型(直到 1.18)、沒有 exception。但如果你從成本角度看,每個限制都是刻意的:

限制 Go 付出的代價 換到的資產
if err != nil 囉嗦 表達力降低 錯誤路徑完全透明
沒有繼承,只有組合 某些模式寫起來更長 零「向上追溯」的認知負擔
gofmt 強制統一格式 失去個人風格 零風格切換成本
GC 而非手動管理 吞吐不如 Rust 穩定的低延遲、更少的 use-after-free

Go 不是不追求效能,它追求的是「在維護成本可控的前提下,效能足夠好」。


「快速足夠」不是擺爛的藉口

「快速足夠」是一個決策濾網,不是偷懶的理由。

當你的服務 P99 是 50ms,SLO 是 100ms,你有兩個選擇:

  • A:花 3 個月優化到 20ms,需要重寫邏輯、加複雜快取
  • B:維持現狀,工程資源投入其他功能

從成本角度,除非你有理由相信流量會在短期內讓 50ms 逼近 100ms,否則 B 是更好的決策。

但「快速足夠」有三個前提,少了任何一個都是在擺爛:

  1. 你有 SLO。 如果沒有明確的效能門檻,「夠了」就只是感覺。
  2. 你有監控。 你要能看見效能趨勢,在逼近門檻之前就知道。
  3. 你能預測。 當前的設計,在兩倍流量下行為可預測嗎?如果你答不出來,你的系統只是「還沒炸」,談不上「夠快」。

效能瓶頸的層級

真的需要優化時,先搞清楚瓶頸在哪一層。延遲差距是數量級的:

層級 延遲等級 典型來源 優化效益
外部延遲 毫秒級 網路、微服務跳轉、DB I/O 最高
內部延遲 微秒級 GC pause、鎖競爭
資料存取 納秒至微秒 Cache miss、記憶體佈局
演算法效率 納秒級 迴圈邏輯、資料結構 通常最低

一個毫秒級的外部延遲優化,效益可能等於幾百個納秒級的演算法微調。很多人花大量精力調 GC 參數、重構演算法,結果瓶頸根本在網路呼叫上。

先跑 profiling,確認瓶頸在哪一層,再決定動哪裡。


制度化:讓對的事變簡單

靠個人紀律維持成本意識是脆弱的。好的團隊把它變成基礎設施:

成本類型 防護機制 核心邏輯
認知負荷 程式碼風格統一、review 標準 限制自由度
依賴成本 依賴審核流程、mono-repo 增加引入摩擦
效能成本 Profiling、效能預算 回饋閉環
演進成本 API 版本策略、CI 卡關 硬性護欄

讓正確的事情變簡單,讓昂貴的錯誤變困難。


結語

我現在寫程式碼之前會先問一個問題:這行程式碼,半年後是資產還是負債?

如果答不出來,通常代表我還沒想清楚。不是說每行程式碼都要分析到死,大部分時候直覺就夠了。但在決定要不要加一層抽象、要不要引入一個依賴、要不要為了 10% 的效能寫出只有自己看得懂的程式碼時,停下來想一下成本,幾乎總是值得的。

Go 的設計本身就是這個哲學的體現:為了五年後仍可維護,願意在今天付出表達力的代價。

人比伺服器貴。這句話幾乎能解掉一半的效能爭論。