隙あらば寝る

うぇぶのかいしゃではたらくえんじにあがかいています

go vendoring

tldr;

  • golangコンパイル時に GO15VENDOREXPERIMENT という環境変数を設定すると vendoring が有効になる。
  • 1.6 でデフォルト有効になるので、配置を変更するだけで透過的に使える
  • 今は周辺ツールの対応中で実用は厳しいが 1.6 が出るタイミングには出そろうはず。

vendoring?

vendoring とは依存ライブラリを自分のリポジトリに取り込むこと。

不意に依存ライブラリが変更されるような場合に強くなる。

一方で追従を意図的に行わない限りずっと古いバージョンを使うことになるというデメリットもある。

主には長期メンテナンスが必要でリポジトリのビルドを安定的に行いたいような場合に行われる。

google の内部リポジトリではこの方式の vendoring を行っているらしい。 (参考)

実践

Source

main.go を以下内容で ~/go/src/github.com/yoru9zine/vendoring-test に置く。

package main

import (
        "github.com/yoru9zine/somelib"
)

func main() {
        somelib.Something()
}

リポジトリの somelib に依存している。

somelib はとりあえず動けばいいので以下。

package somelib

func Something() {
}

Directory

普通の配置ならこうなる。

~/go/src/github.com/yoru9zine
├── vendoring-test
└── somelib

vendoring するならこう。

~/go/src/github.com/yoru9zine
└── vendoring-test
    └── vendor/github.com/yoru9zine/somelib

リポジトリ内に vendor というディレクトリを作成し、その下で GOPATH と同じような配置を行う。 vendor ディレクトリに取り込むような形になる。

Build

このままビルドしてもエラーになるので、GO15VENDOREXPERIMENT を使う必要がある。

といっても環境変数を有効にしてビルドするだけなので以下でOK。

GO15VENDOREXPERIMENT=1 go build

問題点

vendoring 自体の機能ではなく周辺ツールの話になるが、コーディング時のツール対応がまだ完全でない。

具体的には goimports 等が vendoring を理解しないので書くのがつらい。

GO15VENDOREXPERIMENT は 1.6 でデフォルト有効になるので、各ツールは絶賛対応中という状態 (参考)

もう少しすれば対応も終わると思われるが、普及の壁として大きい。

これ以外にもサイズの大きいリポジトリを取り込むのに抵抗があるというケースもあると思うが、これについては納得して使うしかない。

その他

vendoring の仕組みは GOPATH 以外においたディレクトリではうまく動かないので注意。

書き捨てだと /tmp とかに置いてしまうんだけど、こういうケースでは vendoring は機能しない。