Go Modulesの使い方をざっくり調べたのでメモ。
TL;DR
- go.mod内の
module
名にバージョン名が入っているリポジトリがあったmodule github.com/golang-migrate/migrate/v4
- 古いバージョンは使うときはmodファイル内で
replace
を使えばよいreplace github.com/golang-migrate/migrate/v3 latest => github.com/golang-migrate/migrate v3.5.4
- ブランチ名が
v1
のようなバージョン名だとブランチではなく、自動的に関連するリリースタグ状態を確認しにいく模様
以下のコードは同じgithub.com/golang-migrate/migrate
リポジトリの各バージョンを取り込むgo.mod
ファイルだ。
バージョンの指定を"イイ感じ"に判断してもらうため、ひとまずコメントのようにlatest
をした。
go mod tidy
を実行後は依存性を正しく解決した状態になっている。
module github.com/budougumi0617/til/go/modules/branch
go 1.12
// go mod tidyコマンドを行う前の手動で書いたgo.modファイルの依存関係
//
// require (
// github.com/golang-migrate/migrate v1
// github.com/golang-migrate/migrate/v3 latest
//
// github.com/golang-migrate/migrate/v4 latest
// )
//
// replace github.com/golang-migrate/migrate/v3 latest => github.com/golang-migrate/migrate v3.5.4
require (
github.com/golang-migrate/migrate v1.3.2
github.com/golang-migrate/migrate/v3 v3.5.4
github.com/golang-migrate/migrate/v4 v4.4.0
gopkg.in/mattes/migrate.v1 v1.3.2 // indirect
)
replace github.com/golang-migrate/migrate/v3 v3.5.4 => github.com/golang-migrate/migrate v3.5.4+incompatible
なお、この記事の内容はgithub.com/golang-migrate/migrate
の最新リリースがv4.4.0
の時に検証された。
また、goのバージョンは1.12.6である。
go.mod内のmodule名にバージョン名が入っているリポジトリがあった
golang-migrate/migrate
リポジトリのgo.mod
ファイルを見ると、module
名がgithub.com/golang-migrate/migrate/v4
になっていた。
このような状態のリポジトリでv3.X.X
系を使いたい場合はどうすればいいのだろうか?
// https://github.com/golang-migrate/migrate/blob/v4.4.0/go.mod
module github.com/golang-migrate/migrate/v4
require (
cloud.google.com/go v0.37.4
github.com/aws/aws-sdk-go v1.17.7
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/cockroachdb/apd v1.1.0 // indirect
// ....
古いバージョンは使うときはmodファイル内でreplace
を使えばよい
replace
を使うことで、任意の古いリリース状態を使うことができた。
最初にリポジトリのタグやブランチは以下の状態になっている。
$ git branch -r
origin/HEAD -> origin/master
origin/cli-updates
origin/master
origin/v1
origin/v1-gopkg
リリースタグは以下のような状態になっている(一部省略)。
$ git tag -l
v1.2.0
v1.3.0
v1.3.1
v1.3.2
v3.0.0
v3.0.0-prev0
v3.0.0-prev1
v3.0.0-prev2
...
v3.5.4
v4.0.0
v4.0.1
...
v4.4.0
v4.5.0
このような状態のリポジトリのとき、v3
系を利用して開発する場合はreplace
を使えば良さそうだった。
以下のように手で編集したgo.modファイルを用意する。
module github.com/budougumi0617/til/go/modules/branch
go 1.12
require (
github.com/golang-migrate/migrate/v3 latest
)
replace github.com/golang-migrate/migrate/v3 latest => github.com/golang-migrate/migrate v3.5.4
該当リポジトリをimport
するファイルを作成しておく。
package main
import (
"fmt"
database3 "github.com/golang-migrate/migrate/v3/database"
)
func main() {
fmt.Println(database3.GenerateAdvisoryLockId("mod test"))
}
この状態でgo mod tidy
を実行すれば、正しいrequire
とreplace
が指定された状態のgo.mod
ファイルが作成された。
require (
github.com/golang-migrate/migrate/v3 v3.5.4
)
replace github.com/golang-migrate/migrate/v3 v3.5.4 => github.com/golang-migrate/migrate v3.5.4+incompatible
また、v1
ブランチを使いたいときはどうやって使うのだろう?と以下のように設定を追加してみた。
module github.com/budougumi0617/til/go/modules/branch
go 1.12
require (
github.com/golang-migrate/migrate v1
github.com/golang-migrate/migrate/v3 latest
)
replace github.com/golang-migrate/migrate/v3 latest => github.com/golang-migrate/migrate v3.5.4
結果はv1
ブランチではなく、自動的にリリースタグのほうのv1
系が参照された。
require (
github.com/golang-migrate/migrate v1.3.2
github.com/golang-migrate/migrate/v3 v3.5.4
)
replace github.com/golang-migrate/migrate/v3 v3.5.4 => github.com/golang-migrate/migrate v3.5.4+incompatible
v4
系も含めて使おうとすると、go.modは次のようになる。
module github.com/budougumi0617/til/go/modules/branch
go 1.12
require (
github.com/golang-migrate/migrate v1.3.2
github.com/golang-migrate/migrate/v3 v3.5.4
github.com/golang-migrate/migrate/v4 v4.4.0
gopkg.in/mattes/migrate.v1 v1.3.2 // indirect
)
replace github.com/golang-migrate/migrate/v3 v3.5.4 => github.com/golang-migrate/migrate v3.5.4+incompatible
コードの中でどうやって呼ぶかというと、以下のようになる。
package main
import (
"fmt"
"github.com/golang-migrate/migrate/driver"
database3 "github.com/golang-migrate/migrate/v3/database"
database4 "github.com/golang-migrate/migrate/v4/database"
)
func main() {
fmt.Println(database3.GenerateAdvisoryLockId("mod test"))
fmt.Println(database4.GenerateAdvisoryLockId("mod test"))
fmt.Println(driver.GetDriver("mod test"))
}
終わりに
(だいぶ前に調べていたのだが、)渋川さんのTweetをみて調べた内容をまとめた。 挙動を見た、というレベルなのでロジック的な部分の確認は出来ていない。
これのgo moduleがわからん。プロジェクトのルートのgo.modのmoduleは確かにv4ってのが末尾に入っているこれで.../v4でimportできるようになる?v3ってのもreadmeにかかれているけど、これはどこにある?https://t.co/i1QHEPtBn7
— 渋川よしき (@shibu_jp) July 2, 2019
go.modファイルはいつも手で直接編集してしまうのだが、もっとシステマティックに編集するのはどうしたらいいんだろう?