はじめに
go1.11からGo Modulesというのがサポートされていたので、簡単に使い方をご紹介します。
これは簡単に言うとバージョン管理ツールです。 Go 1.11時点ではexperimentalで、最終的にGo1.13で取り込まれるようです。
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
という"rsc.io/quote"に依存したプログラムがあるとき、go buildとすると自動的にgo getしてくれるというものです。
使い方
例として、GOPATHに次のプロジェクトを作成した前提で、使い方を見ていきます。
$ mkdir -p $GOPATH/github.com/kwmt/gomod-sample
$ cd $GOPATH/github.com/kwmt/gomod-sample
まず、go modコマンドというのがあるのですが、そのコマンドを使うためには、GO111MODULE
という環境変数をon
に設定する必要があります。
export GO111MODULE=on
次にgo mod init
で初期化します。
% go mod init github.com/kwmt/gomod-sample
go: creating new go.mod: module github.com/kwmt/gomod-sample
すると、go.modというファイルが作成されます。
% ls
go.mod
ちなみに、go.modファイルの中身は下記のようになっています。
module github.com/kwmt/gomod-sample
Quick Startにあるように、下記のような“rsc.io/quote”というライブラリに依存したプログラムhello.goを作成します。
% cat <<EOF > hello.go
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
EOF
% ls
hello.go
そしてgo buildします。
% go build
go: finding rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
すると、依存ライブラリをダウンロードしてくてるようなログがでてますね。
終わったらgoプログラムのバイナリと、go.sumというファイルができています。
% ls
go.mod go.sum gomod-sample* hello.go
実行してみましょう。
% ./gomod-sample
こんにちは世界。
おぉ、なんといういことでしょう、go getも何もしていないのにgo buildだけで依存解決してくれました。
go.modファイルをもう一度みてみると、require rsc.io/quote v1.5.2
という一文が追加されています。
module github.com/kwmt/gomod-sample
require rsc.io/quote v1.5.2
バージョン管理はrequire <ライブラリ> <バージョン>
とすることでできそうです。
先程はgoプログラムからgo.modに依存ライブラリが書かてた流れになりましたが、逆にgo.modにライブラリ(go-print)を書いてgoプログラムで使えるか見てます。
go.modファイルを次のように編集します。
module github.com/kwmt/gomod-sample
require (
rsc.io/quote v1.5.2
github.com/kwmt/go-print master
)
go build してみると、追加した依存ライブラリをダウロードしてくれてるようです。
% go build
go: finding github.com/kwmt/go-print master
これを使ってみましょう。
index d2c61a0..00167b6 100755
Binary files a/gomod-sample and b/gomod-sample differ
diff --git a/hello.go b/hello.go
index 7475f42..4439d38 100644
--- a/hello.go
+++ b/hello.go
@@ -3,8 +3,12 @@ package main
import (
"fmt"
"rsc.io/quote"
+
+ p "github.com/kwmt/go-print"
)
func main() {
fmt.Println(quote.Hello())
+
+ fmt.Println(p.Print("そうだ京都へ行こう!"))
}
このように変更してみました。
実行してみましょう。
% go run hello.go
こんにちは世界。
そうだ京都へ行こう!
使えてますね。
go.modファイルをもう一度見てみると、masterと書いていたところが、v0.0.0-20170429154625-3ca7e5ea0b96のように変わっています。形式はv0.0.0-<更新日時>-<コミットハッシュ>
ですかね。
github.com/kwmt/go-print v0.0.0-20170429154625-3ca7e5ea0b96
バージョンを指定しない状態でgo buildするとusage: require module/path v1.2.3
と怒られるので何かしら指定しないといけないのですが、tagがプッシュされてないリポジトリとかはmaster
でも良さそうです。
まとめ
- go modコマンドを使うには、現時点では環境変数
GO111MODULE
をon
に設定する。 - go modを使い始めるときは、go mod initで初期化して、go.modファイルを作成する。
- goプログラム側に依存ライブラリを書くか、go.modファイルに依存ライブラリを書いて go buildするだけ。
この記事を書くにあたって試した全体のソースはこちらです。 https://github.com/kwmt/gomod-sample
おわりに
もともとGoogle App Engine(go111)にgovendorを使って複数のライブラリに依存したプログラムをデプロイしようとして、デプロイできなくていろいろ調べていたら、たまたまこのstackoverflowを見てGo Moduleを知りました。 GAEでvendorを使うのはgopathの設定をいじったりしてめんどくさい感じだったのですが、これだとgo buildするだけなのでGAEでも使いやすいかなと思います。 実際Firebase Admin Go SDKを使ってとくにgopathの設定をいじらなくてもデプロイできました。
参考までにFirestoreを使うために次のimportが必要なとき、
import(
"cloud.google.com/go/firestore"
firebase "firebase.google.com/go"
"golang.org/x/net/context"
"google.golang.org/api/option"
)
go build後に更新されたgo.modは次のようになりました。
module <プロジェクト>
require (
cloud.google.com/go v0.26.0
firebase.google.com/go v3.5.0+incompatible
github.com/googleapis/gax-go v2.0.2+incompatible // indirect
github.com/googleapis/gax-go/v2 v2.0.3 // indirect
go.opencensus.io v0.18.0 // indirect
golang.org/x/net v0.0.0-20181220203305-927f97764cc3
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 // indirect
google.golang.org/api v0.0.0-20181229000844-f26a60c56f14
google.golang.org/genproto v0.0.0-20181221175505-bd9b4fb69e2f // indirect
google.golang.org/grpc v1.17.0 // indirect
)