2019年10月23日 星期三

go modules


用途

可以在$GOPHTH外開專案
怕依賴package不見,可以保留依賴檔案(用vendor功能)
同一依賴package,可已有多版本共存在依賴目錄
可以用Goproxy解決有些地方無法使用o get的問題

說明

環境變數要打開 GO111MODULE=on
專案目錄要設定成使用 module : go mod init
專案的外部 package 還是放在$GOPATH/pkg/mod 下
可以保留目前用的外部 package 到 vendor目錄
可選擇使用 vendor 目錄的 package 或用 go mod 抓

流程

  1. 環境變數設置 GO111MODULE=on(使用 go module 模式)
  2. 專案設定使用 module 。 專案目錄下 go mod init。產生 go.mod 檔案。
  3. 安裝外部 package 方法1:go get -u github.com/xxxx/xxx。會更新 go.mod。
    如果 package 沒有在 go.mod 中指定版本,會抓最新的 tag。沒有 tag 會抓最新 commit。
  4. 安裝外部 package 方法2:go mod downloac。下載全部依賴到 $GOPATH/pkg/mod 。
  5. 然後 go 就會到 $GOPATH/pkg/mod 去找需要的外部 package。

原則

  • go get 如果 package 沒有在 go.mod 中指定版本,會抓最新的 tag。沒有 tag 會抓最新 commit。
  • go get 可抓指定的 tag 或 指定的 commit hash。
  • 要更改專案使用的 package 版本,可以直接改 go.mod,然後重新 go get .....
  • 要使用 vendor 目錄的 package: go build, go install, go test 都加上 -mod=vendor 參數。

go111MODULE 設定

  • 只要有設定GO111MODULE=on,就是使用module。
  • 1.13起,專案在 GOPATH 外,且有 go.mod 文件。無論有無設定都等同于 GO111MODULE=on。
  • 專案在 GOPATH 内,且没有 go.mod 文件時,等同於 GO111MODULE=off

go.mod 設定

  • module 定義模組位置
  • require 指定外部 package 及其版本
  • exclude 排除指定的 package
  • replace 只用不同的 package 取代原本的某個 package
module modtest
go 1.12
require (

 github.com/mattn/go-isatty v0.0.8 // indirect
 github.com/sirupsen/logrus v1.4.2
 github.com/ugorji/go v1.1.7 // indirect
 gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
 gopkg.in/yaml.v2 v2.2.2 // indirect
)
exclude github.com/gin-gonic/gin v1.4.0
replace github.com/tedmax100/modtest => ../gomodtest  //用本地目錄或遠端 repo 取代 modtest

go mod 命令

  • go mod init [project dir / or this dir]
  • go mod download
  • go mod tidy
  • go mod vendor
  • go mod edit
  • go mod why

goland IDE

A module 專案時,IDE的 build/test working dir 要在 module 目錄

B module 專案時,IDE的 build/test output dir 不需要在 module 目錄

C Preference/Go/Go Modules(vgo) => Enable



1 Init project to create go.mod

in goland IDE terminal
>go mod init
will create go.mod

2 Create go.sum

in goland IDE terminal
>go test / go build
will create go.mod

or go mod tidy
will create go.mod and add / remove dependencies

go.mod 裡面會紀錄這個project用到的dependencies及版本。
因為是紀錄版本,所以如果作者commit卻沒有tag 版本,那就會對應錯。

3 Dependency 的版本不一定對,要自己確認。

因為dependency 是從某個公開的repository 抓的(多半是github),
他抓的原則是:
a 如果有指定版本,就抓指定版本。
b 抓有tag release版的最新版。

問題

有可能作者commit很多版,但是都沒更新 release tag,這樣就抓不到你要的版本。

方法:

in project direcroty
go get -u github.com/satori/go.uuid@b2ce2384e17bbe0c6d34077efa39dbab3e09123b

這樣會抓回指定commit的版本
go.mod / go.sum裡面,這個 package的版號,會跟著改。

如果是自己寫的package


go.mod檔案的 module 設定要正確,go get 是用這個判斷 module path,
因為 go mod 要從 git server repo 抓 package,
他不會從 local 電腦 的 $GOPATH 抓 package,
所以要把自己寫的 package 也加入 go mod,
要把這個 package 放到 github。
或放到某個自設的 git server 的 repo。

否則使用go mod 會出現  cannot find module providing package  ...... error

go get 抓 github private repository

get get 只使用https
可能需要社 GOPRIVATE 變數
go env -w GOPRIVATE=github.com/abcd

//設定 global config
//好像一定要設成 global, 設local沒用
git config --global url."https://$USERNAME:$ACCESS_TOKEN@github.com".insteadOf "https://github.com"
$USERNAME 就是github username
$ACCESS_TOKEN 就是 user access token, 在 setting => Developer settings => Personal access tokens