入口程式是 Go 應用的系統地圖。它不一定包含最多細節,但應該讓你知道 process 如何初始化、哪些 goroutine 會啟動、HTTP endpoint 如何註冊,以及程式如何關閉。

本章目標

學完本章後,你將能夠:

  1. 用啟動流程理解 Go 應用結構
  2. 看懂 channel 與元件之間的資料流
  3. 理解 context.WithCancel 在關閉流程中的角色
  4. 判斷新增功能應該接在哪個生命週期位置

【觀察】入口流程分成五段

入口程式的核心責任是揭露應用如何啟動,而不是承載所有實作細節。一個稍具規模的 main() 可以切成五個區塊:

區塊責任
Runtime 與日誌設定設定記憶體限制、初始化 slog
環境設定讀取設定檔、環境變數與 port
元件組裝建立 repository、worker、service 或 server
背景工作啟動 worker、queue consumer 或定時任務
對外介面註冊 CLI command、HTTP endpoint 或 WebSocket route

這種切法讓入口同時保留完整脈絡,又不把所有實作細節塞進 main()

【判讀】main() 的價值是揭露依賴關係

main() 的核心價值是讓依賴關係可見。Go 專案常把依賴直接組裝在 main(),好處是維護者能直接看到應用骨架:

1events := make(chan Event, 128)
2notifications := make(chan Notification, 128)
3
4repo := NewNotificationRepository()
5worker := NewWorker(repo, events, notifications)
6server := NewHTTPServer(repo, notifications)

這段程式揭露一個重要事實:repo 負責保存共享狀態,worker 負責處理背景事件,server 負責提供 HTTP 入口。資料如何流動,不需要先查框架設定就能看懂。

【策略】用生命週期判斷功能應該放哪裡

新增功能的核心判斷是:先確認它屬於哪一種生命週期,再決定接入位置。新增功能時,先判斷它屬於哪一種生命週期:

新功能類型接入位置
新 HTTP endpoint入口程式註冊 route,實作獨立 handler
新背景事件來源新增 channel、worker 或 queue consumer
新即時訊息 actionmessage router 或連線管理元件
新狀態欄位repository 更新與 model 擴展
新診斷能力條件註冊 endpoint 或 slog 欄位

這個判斷可以避免把功能塞進錯誤元件,造成後續難測與難改。

【執行】完整啟動路徑

啟動路徑的核心用途是提供除錯地圖。一個有背景工作與 HTTP 介面的 Go 應用,啟動後的主要路徑可能如下:

 1main()
 2  ├─ setup logger / runtime
 3  ├─ create channels
 4  ├─ create repository / worker / server
 5  ├─ context.WithCancel()
 6  ├─ go worker.Run(ctx)
 7  ├─ go startPeriodicSync(ctx)
 8  ├─ go server.Run(ctx)
 9  ├─ register /health
10  ├─ register /ws
11  ├─ register /events
12  ├─ go waitForShutdown(cancel, ...)
13  └─ http.Server.ListenAndServe()

這份路徑也是除錯清單。當應用沒有產生預期輸出時,可以依序確認:輸入來源是否產生資料、worker 是否處理資料、對外介面是否有 client 或呼叫者、狀態資料是否被正確更新。