10分鐘學會go module

基本使用

環境準備

1、golang 1.11的朋友,開啓 GO11MODULE=on ,並且確保實驗目錄不在 GOPATH 中,命令行裏執行。
export GO11MODULE=on
export GO111MODULE=on
2、golang 1.12的朋友,確保實驗目錄不在 GOPATH 中。
3、加速下載,命令行裏執行。
export GOPROXY=https://goproxy.io

https://goproxy.io/zh:必看/

初始化go module環境

帶git的項目

1、直接從github上面clone一個項目下來。
2、直接執行 go mod init 會自動生成帶git地址的packagename

➜  gomodtest_base git:(master)go mod init
go: creating new go.mod: module github.com/e421083458/gomodtest_base

不帶git的項目

1、直接執行

go mod init packagename

下載依賴包

只下載依賴包

go mod download
➜  new_module_test go mod download
go: finding github.com/e421083458/gomodtest_dep v0.0.0-20190501153957-6ff7f41fdb83
go: finding github.com/e421083458/gomodtest_base v1.0.1
go: finding github.com/e421083458/gomodtest_base/v2 v2.0.0
go: finding github.com/jianfengye/collection v0.0.0-20190426092112-28c4a03f0c86
go: finding github.com/pkg/errors v0.8.1

拉取必須模塊,移除不用的模塊

go mod tidy

注意點
1、如果tag對應內容有更新,需要刪除pkg中的緩存內容。這點比較噁心了。

cd $GOPATH/pkg/mod
rm -rf *

2、go get、 go run、go build 也會自動下載依賴

添加新依賴包

方法一: 直接修改 go.mod 文件,然後執行 go mod download

方法二: 使用 go get [email protected],會自動更新 go.mod 文件的

方法三: go run、go build 也會自動下載依賴

將依賴包下載到vendor目錄

go mod vendor

注意: 這裏只會下載對應版本的包文件,不會把所有版本下載。跟之前1.11使用方式一致

亮點功能一:使用replace本地包替換

有時候國外軟件可能被牆,這個功能就能派上用場了。
main.go

main.go

package main
import "my/example/pkg"
func main() {
    pkg.Hello()
}

go.mod

module my-mod

require my/example/pkg v0.0.0
replace my/example/pkg => ./pkg

module my-mod

require my/example/pkg v0.0.0
replace my/example/pkg => ./pkg

module my-mod

require my/example/pkg v0.0.0
replace my/example/pkg v0.0.0 => github.com/example/pkg v0.0.0

注意點: 頂層依賴可替換但間接依賴不可替換

亮點功能二:語意化版本 semver—Semantic Versioning

semver是官方爲了類庫升級引入的新規範,即:
“If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.” - go modules wiki "
如果舊軟件包和新軟件包具有相同的導入路徑,則新軟件包必須向後兼容舊軟件包。"

main.go

package main
import (
    "fmt"
    v1 "github.com/e421083458/gomodtest_base"
    v2 "github.com/e421083458/gomodtest_base/v2"
)
func main(){
    v2.NewIntCollection("hello","sex")
    v1.NewIntCollection("hello")
    fmt.Println("hello");
}

亮點功能三:依賴包衝突問題

情況1:直接 引用的包 和 間接引用的包是同一個包,但版本不同時?

依賴關係:
gomodtest_test|--> gomodtest_dep         |--> gomodtest_base@v1.0.0
              |--> gomodtest_base@v1.0.1    

go mod tidy 時,gomodtest_test會自動更新到與依賴包關聯的第三方包相同版本號,並寫入到go.mod,從而解決了版本衝突問題。

情況2: 間接引用的兩個包是同一個包,但版本不同時?

比如以下場景:
gomodtest_test|--> gomodtest_dep  |--> gomodtest_base@v1.0.0
              |--> gomodtest_dep2 |--> gomodtest_base@v1.0.1

go mod tidy 時,默認使用第一個包引用版本號,[email protected],並寫入到go.mod,這個時候就要注意兩個版本是否功能完全兼容的問題了。

亮點功能四:自動查找包依賴

go mod 遵循了之前go get 自動下載依賴特性。所有的依賴包會自動全部下載。
未啓用 go mod 功能的包會自動下載最高 tag 版本或最高 master commit版本
我之前也以爲go mod只會自動查詢使用了go mod的功能的包。

➜  new_module_test go mod download
go: finding github.com/e421083458/gomodtest_dep v0.0.0-20190501153957-6ff7f41fdb83
go: finding github.com/e421083458/gomodtest_base v1.0.1
go: finding github.com/e421083458/gomodtest_base/v2 v2.0.0
go: finding github.com/jianfengye/collection v0.0.0-20190426092112-28c4a03f0c86
go: finding github.com/pkg/errors v0.8.1

總結:

  • 大部分場景下 go mod init 和 go mod tidy 兩個命令就夠用了
  • 查看$GOPATH/pkg/mod裏面的文件就知道了,mod做了一件類似maven的事把所有包都打上了版本號。
    可以說這是 golang 邁向高大上語言的標誌。
    從此我們不再爲多版本使用的困擾,也不再爲IDE打開一個新項目後等待n分鐘的生成緩存犯愁。推薦大家丟掉vendor使用統一管理。
  • semver 將版本信息綁定進包名對於習慣了傳統包管理器方案的用戶來說顯得有些怪異,可能需要花上一些額外時間適應。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章