Go Modules v2 及後續版本

2021-02-20 Rayjun

在代碼發布到 v2 之後,發布的策略與之前稍有不同,這篇文章介紹了 v2 之後版本的發布方法。

原文地址:https://blog.golang.org/v2-go-modules

簡介

這個系列的文章總共有五篇,這是第四篇:

隨著一個項目的成熟和新需求的增加,過去的特性和設計決策可能要被廢棄。開發人員可能希望通過刪除棄用的函數、重命名類型或將複雜的包拆分為可管理的部分來實踐所學。這些的更改需要下遊用戶將他們的代碼遷移到新的 API 中,因此應該仔細考慮收益與成本,在收益大於成本的情況下才進行更改。

對於仍處於試驗階段的項目(主版本號是 v0),用戶期望偶爾會有突破性的變化。對於那些被聲明為穩定的項目,在主版本 v1 或更高版本中,更改必須在新的主版本中完成。這篇文章探討了主版本的語義,如何創建和發布一個新的主版本,以及如何維護一個模塊的多個主版本。

主版本和模塊路徑

模塊形成了了 Go 中的一個重要原則,即導入兼容性規則:

💡

如果舊的包和新的包有同樣的導入路徑,新的包必須兼容舊的包。

根據定義,包的新主版本與以前的版本不向後兼容。這意味著模塊的新主版本必須具有與前一個版本不同的模塊路徑。從 v2 開始,主版本必須出現在模塊路徑的末尾(在 go.mod 文件的 module 語句中聲明)。例如,當模塊 github.com/googleapis/gax-go 的作者開發 v2 版本時,他們使用了新的模塊路徑 github.com/googleapis/gax-go/v2。想要使用 v2 的用戶必須將他們的包導入和模塊需求更改到 github.com/googleapis/gax-go/v2。

Go 模塊與其他依賴管理系統的不同之處在於,需要使用主版本後綴。後綴需要解決菱形依賴問題。在 Go 模塊出現之前,gopkg.in 允許包的維護者遵循我們現在所說的導入兼容性規則。在 gopkg.in,如果你同時依賴一個導入 gopkg.in/yaml.v1  和另一個 gopkg.in/yaml.v2 包,這不會衝突,因為兩個 yaml 包有不同的導入路徑,它們使用了版本後綴,就像 Go模塊一樣。因為 gopkg.in 與 Go 模塊使用相同的版本後綴方法,Go 命令接受 gopkg.in/yaml.v2 中的 v2 作為有效的主版本後綴。這是為了兼容 gopkg.in 的特殊情況:託管在其他地方的模塊需要使用 /v2 這樣的後綴。

主版本策略

在包括 v2 版本的更高版本中,推薦在以主版本號命名的目錄下進行開發:

github.com/googleapis/gax-go @ master branch/go.mod    → module github.com/googleapis/gax-go/v2/go.mod → module github.com/googleapis/gax-go/v2

這個方法與對模塊無感知的工具兼容:代碼倉庫中的文件路徑與 GOPATH 模式下使用 go get 相匹配。這個策略還允許不同目錄下的主版本同時進行開發。

其他策略可能將主版本保留在單獨的分支上。但是,如果 v2+ 版本的原始碼在倉庫的的默認分支上(通常是 master 分支),那麼不支持版本感知的工具——包括 GOPATH 模式下的 go 命令——可能無法區分主要版本。

這篇文章中的例子將遵循主版本子目錄策略,因為它有最好的兼容性。我們建議模塊作者,如果有用戶在 GOPATH 模式下進行開發,就遵循這種策略。

發布 v2 及後續版本

這篇文章以 github.com/googleapis/gax-go 項目為例:

$ pwd/tmp/gax-go$ lsCODE_OF_CONDUCT.md  call_option.go  internalCONTRIBUTING.md     gax.go          invoke.goLICENSE             go.mod          tools.goREADME.md           go.sum          RELEASING.mdheader.go$ cat go.modmodule github.com/googleapis/gax-go
go 1.9
require ( github.com/golang/protobuf v1.3.1 golang.org/x/exp v0.0.0-20190221220918-438050ddec5e golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b google.golang.org/grpc v1.19.0 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099)$

在開始開發 github.com/googleapis/gax-go 的 v2 版本時,我們會創建一個 v2 目錄,並把所有的包都拷貝進來:

$ mkdir v2$ cp *.go v2/building file list ... donecall_option.gogax.goheader.goinvoke.gotools.go
sent 10588 bytes received 130 bytes 21436.00 bytes/sectotal size is 10208 speedup is 0.95$

然後把當前的 go.mod 文件也拷貝到 v2 目錄下,並在模塊路徑後面增加 v2 後綴:

$ cp go.mod v2/go.mod$ go mod edit -module github.com/googleapis/gax-go/v2 v2/go.mod$

需要注意 v2 版本與 v0/v1 版本都是是被當做一個單獨的模塊:但兩者可能使用了相同的構建。因此,如果你的 v2+ 版本模塊有多個包,你應該更新它們以使用新的 /v2 導入路徑。否則,你的 v2+ 模塊就依賴你的 v0 / v1 模塊。所以要將所有 github.com/my/project 引用更新到github.com/my/project/v2,可以使用 find 和 sed :

$ find . -type f \    -name '*.go' \    -exec sed -i -e 's,github.com/my/project,github.com/my/project/v2,g' {} \;$

現在我們有了一個 v2 版本的模塊,但是我們想在發布一個版本之前進行試驗和修改。在我們發布v2.0.0(或任何沒有預發布後綴的版本)之前,我們可以在決定新 API 之前進行開發或做出破壞性的更改。如果我們想讓用戶在我們正式發布新 API 之前能夠試用它,我們可以發布一個 v2 的預發布版本:

$ git tag v2.0.0-alpha.1$ git push origin v2.0.0-alpha.1$

一旦 v2 版本的 API 已經穩定,並確定不需要做任何破壞性的更改,我們可以發布正式版本,標記 v2.0.0:

$ git tag v2.0.0$ git push origin v2.0.0$

到目前為止,有兩個主版本需要維護。向後兼容的更改和錯誤修復將產生新的次版本和補丁版本(例如,v1.1.0, v2.0.1,等等)。

結論

主版本變更會產生更多的開發和維護開銷,並需要下遊用戶配合遷移。項目越大,這些管理代價就越大。只有在確定非做不可的原因之後,才應該進行主版本的變更。一旦修改原因被確定是一個破壞性變更,我們建議在主分支中開發多個主版本,因為這種方式能夠最大化的與現有工具兼容。

對 v1+ 版本模塊的破壞性更改應該總是發生在 vN+1 版本模塊中。當新模塊發布時,這意味著模塊的維護者和需要遷移到新版本的用戶需要做額外的工作。因此,維護者應該在發布一個穩定的版本之前驗證他們的 API,並仔細考慮在 v1 版本之外是否真的有必要做大版本的變更。

另外,騰訊雲區塊鏈方向在大量招人,包括前端、後端、架構師、產品等諸多崗位,如果感興趣,請把簡歷投過來 rayjun0412@gmail.com。

譯 / Rayjun

相關焦點

  • 【Go技術】Go Modules概述
    GO111MODULE 環境變量 這個環境變量主要是用於 Go modules 的開啟或者關閉。這個屬性有三個值分別如下所示:GOPROXY 環境變量 這個環境變量主要是用於設置 Go 模塊代理(Go module proxy),其作用是用於使 Go 在後續拉取模塊版本時能夠脫離傳統的 VCS 方式,直接通過鏡像站點來快速拉取。
  • 第 61 期 乾貨滿滿的 Go Modules 和 goproxy.cn
    go.sumgo.sum 是類似於比如 dep 的 Gopkg.lock 的一類文件,它詳細羅列了當前項目直接或間接依賴的所有模塊版本,並寫明了那些模塊版本的 SHA-256 哈希值以備 Go 在今後的操作中保證項目所依賴的那些模塊版本不會被篡改。example.com/apple v0.1.2 h1:WX...
  • go modules:使用mod管理項目依賴包,通過vendor一鍵分發編譯包
    在go語言1.11版本之前,沒有modules機制,所有軟體包都在安裝在$GOPATH/src目錄下。不同項目如果引用了同一個軟體包的不同版本,就會造成編譯麻煩。修改$GOPATH變量是當時一種比較簡單的解決方案。從1.11版本開始,開始有了GO111MODULE變量。因為是自1.11版本支持的,所以名字中有「111」。
  • 從此再無包下載的任何煩惱:看高手是如何參透 Go Module 的?
    go.sumgo.sum 是類似於比如 dep 的 Gopkg.lock 的一類文件,它詳細羅列了當前項目直接或間接依賴的所有模塊版本,並寫明了那些模塊版本的 SHA-256 哈希值以備 Go 在今後的操作中保證項目所依賴的那些模塊版本不會被篡改。example.com/apple v0.1.2 h1:WX...
  • 一篇文章教會你如何使用Go語言Modules
    moudules是Go的一個包管理工具,官方提供的,還是比較靠譜的,最低Go版本要求1.11+。go modules的,不需要做其他設置。它和傳統的直接go get區別在哪沒有使用go modules時,我們直接go get下載的包,會默認放在%GOPATH%/src目錄下。
  • go-mir v2.0.0 發布,用 Go 結構體標籤定義 handler 路由信息的...
    go-mir v2.0.0 發布了,推薦使用。
  • go protobuf v1敗給了gogo protobuf,那v2呢?
    一. go protobuf v1 vs. gogo protobufgogo protobuf是既go protobuf官方api之外的另一個go protobuf的api實現,它兼容go官方protobuf api(更準確的說是v1版本)。
  • 前端基礎進階(15):詳解 ES6 Modules
    下載地址: http://nodejs.cn/download/2、安裝一個好用的命令行工具在windows環境下,系統默認的cmd非常難用,所以我個人比較推薦大家使用git.bash 或者 cmder。
  • Go 語言 Excel 類庫 Excelize 2.0.0 版本發布
    2019年4月23日, 社區正式發布了 2.0.0 版本,該版本包含了很多新功能、錯誤修復和性能優化。下面是有關該版本更新內容的摘要,完整的更改列表可查看 change log.Release Notes此版本中最顯著的變化包括:API 更改下表列出了 v2.0.0 相比較於 v1.4.1 版本,API 的更改情況: 函數名 增加 error
  • DRYCC Workflow v1.3.0 版本發布
    目前的最新版本採用k8s的ingress重寫了路由部分,並支持自動acme證書,以及擁有heroku-16和heroku-18雙STACK支持。Workflow ## v1.2.0 -> v1.3.0Releases builder v1.0.2 -> v1.1.0 slugbuilder v1.1.0 -> v1.1.1 dockerbuilder v1.1.0 -> v1.1.1 controller v1.2.0 -> v1.2.1 slugrunner v1.1.0 -> v1.1.1 database
  • Go-Spring 迄今最穩定版本發布了!
    Go-Spring 迄今最穩定版本 v1.0.4 正式發布了!本次更新重點在 Web API 完善和 BeanSelector 實踐上面。同時這個版本的 API 絕對穩定,大家可以放心地在生產環境中使用了!詳細的更新內容如下:go-spring-parent1.
  • DoraCMS v2.0.2 發布,Node.js CMS 內容管理框架
    群眾的力量是偉大的,近期童鞋們針對目前doracms存在的問題提出來很多建設性的建議,也提出了遇到的問題和存在的bug,在這裡要特別感謝@PirateD 和  @amor520  以及@dolare,提出建議和貢獻代碼,具體修復問題如下:1、升級 log4js 到最新版本
  • Go 問題集 - cannot find main module; packages.Load error
    help modules' : packages.Load error」。If you believe this is a mistake, please file an issue: https://github.com/golang/go/issues/new. go [-e -json -compiled=true -test=true -export=false -deps=true -find=false -- ./]: exit status 1: go: cannot
  • 新裡程碑:Cocos2d-x v3.0 正式版本發布!
    歷經半年多的精心打磨,Cocos2d-x v3.0正式版本最終發布!
  • V (Vlang) 首個主要版本 0.2 發布,安全快速可編譯的靜態語言
    V (Vlang) 0.2 發布了,作者宣布這是首個主要版本,更新重點是提升穩定性和優化編譯時(compile-time)內存管理
  • 基礎 | 詳解 ES6 Modules
    但是一般我推薦大家使用iterm2,並安裝oh my zsh插件。具體的配置大家可以自己去折騰,網上的教程應該足夠幫助你搞定這一切了。1、iterm2 下載地址 http://www.iterm2.com/downloads.html2、oh my zsh 主題選擇 https://github.com/robbyrussell/oh-my-zsh/wiki/External-themes
  • DRYCC Workflow v1.3.0 版本發布 - OSCHINA - 中文開源技術交流社區
    目前的最新版本採用k8s的ingress重寫了路由部分,並支持自動acme證書,以及擁有heroku-16和heroku-18雙STACK支持。Workflow ## v1.2.0 -> v1.3.0Releases builder v1.0.2 -> v1.1.0 slugbuilder v1.1.0 -> v1.1.1 dockerbuilder v1.1.0 -> v1.1.1 controller
  • Win10不同版本份額最新統計:一年前的v1909第一、v2004快速增長
    微軟的Windows 10(以下簡稱Win10)保持著每年升級2個版本的節奏,現在大家升級到什麼版本了?根據最新報告,去年下半年的Win10 v1909成為當前份額最高的Win10系統。Adduplex公司每個月都會發布一份Win10份額報告,基於5000多個使用他們家AdDuplex SDK v.2或者更高版本的微軟應用收集來的數據,有一定的參考性。
  • Robotgo v0.90.0 發布,Go GUI 自動化,大幅度更新
    Robotgo v0.90.0 發布了,Golang 跨平臺控制滑鼠、鍵盤、位圖、屏幕、窗口句柄以及全局事件監聽。
  • 解讀Go語言的2020:變革前夜
    模塊:終於穩定 自 2020 年 2 月份發布的 1.14 版本起,Go 語言官方就開始正式地推廣 go modules 了。這說明它已經完全可以在生成環境中使用了。 如果你是老牌的 Go 工程師的話,那麼肯定使用過像 glide、dep、govendor 這類第三方的依賴管理工具。