[TOOLS] 12 分鐘閱讀OraCore 編輯部

Go 支援政策把發版變清單

我把 Go 的支援表改成可直接照抄的升級清單,讓你用版本政策管理發版,不再靠記憶和運氣。

分享 LinkedIn
Go 支援政策把發版變清單

我把 Go 的支援表改成可直接照抄的升級清單,讓你用版本政策管理發版,不再靠記憶和運氣。

我用 Go 管過一陣子之後,最煩的不是語法,也不是編譯器脾氣,是大家老愛問一句:「這版到底能不能上?」程式能跑、測試能過,到了資安審查或維運交接,整個信心直接掉一半。更煩的是,很多團隊只記得自己升過版,卻忘了那條線到底還在不在支援期。Go 其實沒把這件事搞得很玄,反而很規矩。問題通常是我們自己,把版本管理當背景雜訊,直到它變成 production 問題才開始補作業。

後來我改掉一個習慣:不再把版本支援表當冷知識,而是當工作文件。我開始固定看 endoflife.date 的 Go 頁面,像看 lockfile 一樣看它,不是為了懷舊,是為了知道哪些版本還能安心跑。這個轉念很實際,因為它直接改變我怎麼排升級、怎麼跟 security team 講話、怎麼決定哪些服務該先推進,不要再裝死。

別問最新版,先問還支援哪幾版

訂閱 AI 趨勢週報

每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。

不會寄垃圾信,隨時可取消。

Each major Go release is supported until there are two newer major releases.

這句話就是整個遊戲的核心。Go 的支援政策不是那種「大概會照顧一下」的模糊說法,而是很簡單的滑動窗口:保留目前版本和前兩個 major release,舊的就慢慢退場。endoflife.date 的 Go 頁面把這個政策整理得很直接,也跟官方 Go security policy 對得上。

Go 支援政策把發版變清單

白話翻譯就是:最新不等於還在支援,而我在 production 裡只在乎後者。這點我看過太多團隊搞混。有人很驕傲地說:「我們只落後一個 minor。」聽起來很保守,實際上可能是在一條已經掉出支援窗的線上自我安慰。那不叫穩健,那叫把風險包裝得比較好聽。

我之前就遇過一個團隊,明明服務還在跑,卻完全沒人知道它已經踩在支援邊緣。等到安全稽核來問,大家才手忙腳亂翻文件。那種場面很熟:不是不能升,是平常沒人把它當回事。結果一有壓力,所有版本決策都變成臨時抱佛腳。

實操寫法很簡單:把內部政策寫成「支援中的 major release」而不是「我們喜歡的最新版」。如果現在是 Go 1.26,而 1.27 還沒出,1.24 之類已經出局的版本就別再放進新服務。把支援窗寫進 engineering standard,放進部署文件,讓每個人都看得到。

  • 追蹤的是目前支援中的 major,不是只看 patch 號。
  • 新服務直接禁止使用已失支援的 major。
  • 把提醒設在 major release 的節奏,而不是只盯 patch day。

Patch 號才是日常維運的真功夫

很多人只盯 major,覺得升上去就結束了。其實 patch 才是 boring work 的本體。像頁面上會列出最新 patch,例如 Go 1.26.4 是 1.26 線上的最新版本,Go 1.25.11 是 1.25 線上的最新版本。這些數字看起來小,差別卻很大,因為它決定你是在「正確的線上」,還是在「正確的線上但還留著舊 bug」。

也就是說,支援不是二選一。某條 release line 還活著,不代表你停在第一個 patch 也沒差。很多團隊很愛說:「我們已經升到 1.25 了。」聽起來像完成任務,實際上只是完成了一半。你如果卡在 1.25.0,不跟進後續 patch,等於把修好的 bug 和安全修補通通丟掉。

我碰過一個服務團隊,想把 major 統一到新的版本,卻堅持接下來三個月都不碰 patch。理由很熟:「major 已經升完了,剩下不急。」結果後來不是編譯器怪問題,就是某個修正已經被 upstream 補掉,自己還在那邊 debug 半天。Patch 更新真的比 emergency debugging 便宜太多,這件事我已經懶得再證明。

實操寫法:把 major upgrade 跟 patch maintenance 拆成兩條流程。major 可以每季或每半年排一次,但 patch 應該是日常維護。若你有 CI,就讓它預設測最新 patch 的 supported line,不要測舊版本測到自己很感動。

  • 每個 active major 保留一個 current supported patch。
  • Base image 跟著 patch release 一起更新。
  • 保留短 rollback 路徑,但別把 rollback 當成不更新的藉口。

支援表不是博物館,是排程器

endoflife.date 的表很乾脆:Go 1.26 還在支援,1.25 也還在,1.24 以前已經結束。這不是歷史資料而已,這是排程素材。我現在看這種表,腦中只會跑三個問題:我們現在跑哪版、下一個該升哪版、哪些版本已經可以直接列入淘汰清單。

Go 支援政策把發版變清單

白話講,就是你可以把靜態支援表變成 migration queue。只要知道 1.24 在 1.26 出來後就結束,那還卡在 1.24 的服務就不該再被放進「之後再說」的 bucket。它已經是「排進 sprint,或者接受風險」的問題了。這比在 postmortem 才討論,舒服太多。

我最受不了的是,很多團隊把「還能跑」跟「可以忽略」混在一起。這兩件事根本不同。Unsupported software 很常能撐到你以為沒事的那一天,然後它就突然不是 routine patch,而是 forced upgrade。那種時候 build script、CI 設定、部署流程全部一起炸,真的很折磨人。

實操寫法:先做一份小型 inventory,把組織內每個 Go runtime 都列出來。每個 service 標註 major version 和 support status,然後按風險排序,不要只按年齡排序。低流量內部工具也可能很重要,尤其它如果是別人 build artifact 的上游。

Go 的規矩很簡單,所以大家才容易看漏

Go 官方說得很明白:受支援的 release 會拿到 critical fixes,包括重大安全問題,必要時會用 minor revision 來修。這句話其實很兇,因為它把 maintenance line 劃得很清楚:支援中的版本有修補,不支援的沒有。不是建議,是 operating model。

也就是說,你的升級策略應該是跟支援窗對齊,不是跟團隊有沒有空對齊。我很希望這是常識,但實務上我一直看到大家用方便當決策依據。「晚點再升兩個 major。」「等下一個 sprint。」「這個服務很小,先放著。」這些話聽久了,就會變成一堆例外,而例外一多,整個版本管理就爛了。

實操寫法:工程手冊裡直接寫一句。我的版本很直白:production 不得部署在已失支援的 Go major 上,除非有核准例外,而且要有截止日期。 這句話很土,但很有效。它會逼平台、資安、服務 owner 都講同一種語言。

如果你要找官方依據,先看 Go security policy,再看 Go release history。我寧可丟這兩個連結給人,也不要在會議裡靠記憶硬拗。

把 endoflife.date 當成快速驗證層

我喜歡 endoflife.date 的原因很簡單:它把儀式感拿掉了。它直接給我 current release、支援窗口、最新 patch、end date,我不用翻 changelog 翻到眼睛痛。Go 頁面還有 API、RSS、calendar feed,代表它不只適合瀏覽器,也能接進自動化。

白話翻譯就是:當有人問我「1.25 還安全嗎」,我不需要猜,也不需要在三份文件裡找答案。我可以直接查頁面,確認 1.25 還在不在支援窗,然後回答「可以」或「可以,但要快點升」。這個差異很重要,因為它會直接影響 ticket 是這週處理,還是拖到下個季度。

我也用過 RSS 和 calendar feed 來做 release awareness,不想自己再造一套提醒系統。這種東西一點都不帥,但被 support cutoff 暗算更不帥。重點是減少驚訝。讓表幫你做 boring part,本來就是好 reference 該做的事。

實操寫法:把這個頁面當成 team docs 的 source of truth,再視需要自動化。你如果管很多服務,就訂閱 feed,順手把 API 接進 inventory tooling。不要靠記憶、Slack 口耳相傳,或那句最危險的話:「我印象中去年有升。」

  • 把 Go 頁面加到 incident review 的書籤列。
  • 如果你有內部 dashboard,就用 API 拉版本狀態。
  • 如果你管平台,直接訂 RSS 或 calendar feed。

把支援窗寫進 release 流程,不要只寫在 wiki

我後來越來越偏執,因為我看過太多「標準」只存在 wiki,實際上沒人理。Go upgrade 不該是單獨的雜務,而要被當成 release governance。只要某個 service 是用 Go 發的,那 release 流程就應該知道哪些 major 可以用、哪些快到期、哪些直接封殺。

也就是說,build 和 release pipeline 應該在 drift 變成問題前就把它擋掉。要阻止新服務跑在已失支援的 runtime 上,遠比之後把整個 fleet 慢慢拖上來便宜。我處理過那種舊系統綁滿假設的狀況,真的不是每次都能優雅收尾。

實操寫法:在 CI 裡加 runtime check,unsupported major 直接 fail。把 approved version list 放在 platform team 擁有的 repo。再教 service owner 把支援表當成 CVE advisory 一樣看。你如果本來就會追 package 安全問題,這只是把同樣的肌肉用在 release policy 上。

最後提醒一句:不要把 policy 跟 panic 混在一起。Go 的節奏夠穩,你其實可以很平靜地排升級。真正需要的不是英雄式大改版,而是固定習慣。習慣一旦立住,這件事就會變得很 boring,而 boring 在維運裡通常是好事。

可抄的模板

# Go runtime support policy for internal services

## Allowed versions
- Production services must run on a supported Go major release.
- Supported means the current major release and the two prior major releases.
- Patch releases should stay current within the supported line.

## Required checks
- CI must fail if `go version` reports an unsupported major.
- New services must choose from the approved version list.
- Existing services must be reviewed when a major release enters or leaves support.

## Upgrade cadence
- Patch upgrades: monthly, or sooner for security fixes.
- Major upgrades: plan before the current version exits the support window.
- Exceptions: require an owner, a reason, and an end date.

## Operational checklist
1. Inventory every service and its Go version.
2. Compare each version against the current support table.
3. Prioritize services on unsupported majors.
4. Upgrade patch versions on supported lines.
5. Remove any exception before its end date.

## Reference sources
- Go support policy: https://go.dev/security/
- Release history: https://go.dev/doc/devel/release
- Support status page: https://endoflife.date/go

如果你想讓這份東西不只是文件,而是真的會擋風險,就把它接進 CI 和 deployment gate。這差很多。我看過太多「政策」只活在 wiki 裡,結果一到要發版,大家還是照舊憑感覺。那種標準沒有用,真的只是裝飾。

我這篇拆的是 endoflife.date/go 的支援表思路,表格、日期、release status 都來自那裡;政策解讀和這份 workflow template 是我自己整理的。若你要看 Go 官方的維護規則,先從 go.dev/security 開始,再拿支援表去把團隊的版本管理拉回現實。