你在一個 Python 後端工作了兩年。某天,你被拉去 debug 同事寫的 Go 服務。

第一個感覺是:完全不知道從哪裡開始。Goroutine 是什麼?err != nil 為什麼要一直重複?這個 chan 又是什麼東西?

一個月後,你學完基本 Go 語法,勉強能改 bug 了。但你還是有種感覺:你只是在記 Go 的「英文單字」,沒有真的搞懂它在說什麼。

這種感覺有個名字:語法會,模型不會。


語法是皮,模型是骨

Python 有 threading.Thread。Go 有 goroutine。JavaScript 有 async/await。Java 有 ExecutorService

這四個東西的語法完全不同。但它們在解的是同一個問題:你有多件事情要同時處理,OS 只給你有限的 CPU,怎麼辦?

這個問題背後有一個模型:並行(concurrency)。理解了這個模型,你就知道為什麼 Go 的 goroutine 比 OS thread 便宜、為什麼 Node.js 能用單一 thread 應付大量請求、為什麼 Python 的 asynciothreading 是兩件不同的事。

不理解這個模型,你只能記住「用 Go 要 go func()」,遇到問題時不知道發生了什麼。

跨語言共通概念,就是這些底層模型。

語法是表達方式,模型是被表達的東西。


五個不換的模型

換語言時,以下五個模型永遠都在,只是長相不同:

並行模型:這個語言用什麼機制讓多件事同時進行?OS thread?Coroutine?Event loop?Actor?

這個模型決定了你能撐多少並行連線、CPU 密集任務會不會把服務卡死、你需不需要手動寫鎖。Python 的 asynciothreading 在語法上都算「並行」,但底層模型完全不同——搞不清楚這一點,你換 Node.js 或 Go 的時候同樣會栽。

記憶體模型:程式的記憶體誰負責收?Go 和 Java 有 GC,Rust 用 ownership,C/C++ 要手動。選擇不同,效能特性和可能的 bug 類型就不同。

型別系統:這個語言在哪個階段抓型別錯誤?編譯時還是執行時?型別是結構相符就好(TypeScript)還是名字要一樣(Java)?

IO 模型:讀一個檔案、打一個 API,這個「等待」是阻塞 thread 還是非阻塞?底層機制是 epoll 還是 io_uring?

錯誤處理模型:出錯時這個語言要你怎麼辦?Exception(Python、Java)?Result type(Rust)?return error value(Go)?每種選擇對程式碼結構的影響完全不同。


這五個模型,在任何後端語言裡都能找到對應的實作。知道模型在哪、長什麼樣,你就能快速定位新語言的對應位置,而不是從頭摸索。

和 framework 概念的關係

你可能已經讀過 backend/framework/generic/ 系列。那個系列講的是框架層的決策——為什麼選 Express 不選 Django、DI 怎麼用、middleware 怎麼串。

B01 這個系列在更底一層。

framework 說「FastAPI 用 async 函式,Django 用 sync 函式」。
B01 說「async 底層是 event loop,event loop 的原理是什麼、為什麼比 thread 省資源」。

framework 文章預設你知道「並行模型是什麼」。B01 補的就是這個前提。如果你已經讀過 framework 系列,B01 會讓那些選型決策變得更有根據;如果你從 B01 開始,再去讀 framework 系列,很多東西會突然通。


這個系列怎麼讀

B01 的文章分六組。前兩組(01–08)是背景——為什麼要懂這些、這些概念怎麼演進來的。第三組開始才是具體的模型解析:變數/記憶體、並行/IO、錯誤處理、型別系統。最後兩篇是三語言的實作比較,把前面的模型拿來實際對照。

你不需要全部讀完才能用。如果你正在學 Go,可以直接跳到 12(並行 primitives)10(記憶體管理),再回來看 06(並行模型演進) 補上下文。

B01 完整文章列表