支持無聊軟體的理由:為什麼你應該直接使用 Go
在現代軟體開發時代,存在著一種普遍的過度工程化傾向。我們看到 CRUD 應用程式使用一大堆 TypeScript 建置工具、十五種不同的 Node 套件,以及一個完整的 Kubernetes 集群,僅僅是為了提供一個簡單的表單。業界已逐漸轉向一種「聰明」的文化,其中技術棧的複雜度往往被誤認為是產品的精細程度。
有一個強而有力的論點支持回歸基礎。Go (Golang) 代表了這種哲學:它刻意地保持無聊、極簡,並且是為了交付而非學術純粹性而設計的。透過剝離那些經常導致「依賴地獄」和部署噩夢的抽象層,Go 允許開發者專注於唯一真正重要的事情:產品。
無聊的力量
Go 的設計是一種刻意的克制。它避開了裝飾器 (decorators)、元類別 (metaclasses)、巨集 (macros) 和複雜的特性 (traits)。相反,它提供了一組精簡的原語:structs、functions、interfaces、goroutines 和 channels。
這種簡單性服務於關鍵的業務目的。當一種語言是「無聊」的,兩年前由首席工程師編寫的程式碼,對於今天的初級開發人員來說仍然是可讀的。缺乏複雜的抽象層可以防止「聰明」的開發者將十七層的層級結構偷偷塞進程式碼庫中。透過 gofmt,關於空白字元和格式化的爭論被永久解決了,確保了 diffs 保持微小,並讓焦點保持在邏輯上。
標準函式庫即框架
Go 最顯著的優點之一是其全面的標準函式庫。在許多生態系統中,啟動專案的第一步是選擇一個框架(例如:Express、Django、Rails)。在 Go 中,標準函式庫 就是 框架。
使用 net/http 進行路由、html/template 進行渲染,以及 embed 將資產直接編譯進二進位檔中,開發者可以建立一個功能完備的 Web 應用程式,而不需要任何第三方依賴。這消除了對龐大的 node_modules 資料夾和複雜建置流程的需要。
Go 標準函式庫的核心支柱包括:
io.Reader與io.Writer:這些簡單的介面允許數據的無縫串接,從 HTTP 回應到 gzip writers 到磁碟檔案。context.Context:一種標準化的方式來處理跨 API 邊界的取消與超時,防止 goroutines 洩漏和殭屍資料庫查詢。encoding/json與database/sql:一致且基於指標的數據處理與持久化操作。
併發處理而不具備複雜性
Go 是為雲端時代設計的。Goroutines 並非 OS threads;它們是輕量級、多路複用的實體,啟動成本大約僅 2KB。這使得單台筆記型電腦就能產生數十萬個併發操作,而不會產生與傳統執行緒或 async/await 事件迴圈相關的開銷。
Channels 提供了一種強型別的方式讓這些 goroutines 進行通訊,並在內部處理同步。雖然語言提供了 sync.Mutex 用於共享狀態,但主要的模式是透過通訊來共享記憶體,而不是透過共享記憶體來通訊。
部署:從複雜到複製即可
Go 與其競爭對手之間最顯著的對比或許就是部署流程。當其他語言需要複雜的執行環境、虛擬機或多階段 Docker 建置時,Go 編譯成單一、靜態連結的二進位檔。
部署 Go 應用程式可以非常簡單:
- 為目標 OS/Arch 建置二進位檔。
- 透過
scp將檔案複製到伺服器。 - 重啟一個 systemd unit。
這種「複製即執行」模式消除了對 Helm charts、service meshes 以及困擾容器化環境的持續性基礎鏡像 CVE 警報的需要。
反對論點:Go 的不足之處
儘管有其優勢,Go 並非萬靈丹。社群與批評者指出了一些經常出現的痛點點:
錯誤處理的冗長性
無處不在的 if err != nil 模式是最常見的抱怨。批評者認為這讓程式碼充斥著 Repetitive boilerplate,使其更難發現真正需要獨特邏輯的錯誤處理區塊。雖然支持者認為這強迫了在每個失敗點進行顯式決策,但其他人則認為 Rust 的 ? 運算子是解決相同問題更優雅的方案。
生態系統缺口
因為 Go 避開了「肥大框架」的方法,開發者經常發現自己必須為常見的 Web 任務重新造輪子。正如一位批評者所言,像資料庫遷移 (database migrations) 或複雜的 CSS 預處理 (CSS preprocessing) 這樣的基本任務,並非由標準函式庫開箱即用提供,這迫使開發者必須自行實作解決方案,或是在破碎的第三方函式庫景觀中進行篩選。
型別系統的局限性
與 Rust、Haskell 或甚至 C# 等語言相比,Go 的型別系統是初步的。缺乏代數數據型別 (ADTs) 和強大的 enum 系統,意味著某些數據模式必須透過「黑客手段」來實作,增加了在腦中維持軟體結構所需的認知負荷。
結論:選擇正確的工具
Go 經常被描述為程式設計的「Honda Odyssey」:它不是最快的或功能最豐富的,但它非常可靠,且能精確地完成它需要做的事情。
在複雜度不斷上升的時代,選擇使用一種「無聊」的語言通常是一種策略性的選擇。透過優先考慮可維護性、部署簡單性與可讀性,而非語言的優雅性或框架的威力,Go 讓團隊能夠交付持久的軟體。無論是單體架構 (monolith) 還是微服務 (microservice),目標始終如一:建立它、交付它,並讓它運行。