LoginSignup
3
1

More than 5 years have passed since last update.

Goとvendoring

Last updated at Posted at 2018-11-18

お題

Goにとってvendoring(versioningでもあるかな)は長年の課題であるようで、「GoにはGenericsがない!」と同様、ホットな議論が繰り返されてきた。
そうした議論の中で現在試せる最新のツールが「Go module」ということになる。

経験上、GoにはVer1.7と1.9とで、それぞれglidedepといったvendoringツールにお世話になってきた。
個人的にはこれらのツールに大きな不満はなかった(もちろんハマることはあったし、実務レベルで言うとどうにかならないかと思う課題もあったけど、そんなのはどのツールを使っても一緒)のだけど、やはり公式に(dep自体もGo自身にvendoring(versioning)の機能を持たせるための実験的なツール)ツールを提供してくれるなら、それを使いたい。

というわけで、Go moduleを使ってみようなんだけど、ついでなので、これまでに自分が使ってきたツールでの方法を振り返ってみる。

開発環境

# OS

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="17.10 (Artful Aardvark)"

# Golang

$ go version
go version go1.11.2 linux/amd64

バージョンの切り替えはgoenvで行っている。

実践

■GOPATHで依存パッケージ解決

試行ソースは下記。
https://github.com/sky0621/go-modules/tree/4f5e5a5187c79413550655c9620d539923c65615

環境変数でGOPATHをセット

$ env | grep GOPATH
GOPATH=/work/src/golang

GOPATH配下にソースを配置

$ pwd
/work/src/golang/src/github.com/sky0621/go-modules
$ tree
.
├── cmd
│   └── main.go
└── rootpackage.go

main.go

同じプロジェクトの別パッケージ「github.com/sky0621/go-modules」の関数を実行する。
また、別プロジェクト(github.com/satori/go.uuid)の関数を実行する。
GOPATH配下に↑が置かれるよう$ go get github.com/satori/go.uuidしておく。

package main

import (
    "fmt"

    "github.com/sky0621/go-modules"

    uuid "github.com/satori/go.uuid"
)

func main() {
    fmt.Println("Hello, World!")
    modules.SayBye()
    u1 := uuid.Must(uuid.NewV4())
    fmt.Printf("UUIDv4: %s\n", u1)
}

実行結果。

$ pwd
/work/src/golang/src/github.com/sky0621/go-modules/cmd
$ go run main.go 
Hello, World!
Bye!
UUIDv4: 2a601fdb-fe9d-49e7-81b8-15b554d2e42e

備考

プロダクトでGOPATH指定でのビルド・デプロイはしたことがない。
例えばKubernetesを使う(いや、使わなくてもDockerコンテナを使う)場合、dockerfileGOPATHをセットする記述をして、外部依存パッケージを軒並みgo getしていく記述もする感じなのだろうか。で、最後にバイナリにする。

■Vendoring( glide )で依存パッケージ解決

例えば、GOPATH配下にアプリが使っているパッケージが存在しなかった場合、go runした時にエラーが起こる。

$ env | grep GOPATH
GOPATH=/work/src/golang
$ ll /work/src/golang/src/github.com/satori
ls: '/work/src/golang/src/github.com/satori' にアクセスできません: そのようなファイルやディレクトリはありません
$ pwd
/tmp/go-modules/cmd
$
$ go run main.go 
main.go:8:2: cannot find package "github.com/satori/go.uuid" in any of:
    /home/koge/.goenv/versions/1.11.2/src/github.com/satori/go.uuid (from $GOROOT)
    /work/src/golang/src/github.com/satori/go.uuid (from $GOPATH)
main.go:6:2: cannot find package "github.com/sky0621/go-modules" in any of:
    /home/koge/.goenv/versions/1.11.2/src/github.com/sky0621/go-modules (from $GOROOT)
    /work/src/golang/src/github.com/sky0621/go-modules (from $GOPATH)

glideのインストールと適用

インストール

$ curl https://glide.sh/get | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4833  100  4833    0     0   1611      0  0:00:03  0:00:03 --:--:--  1294
  〜〜〜 省略 〜〜〜
Downloading https://github.com/Masterminds/glide/releases/download/v0.13.2/glide-v0.13.2-linux-amd64.tar.gz
glide version v0.13.2 installed successfully

適用

$ pwd
/tmp/go-modules
$
$ glide init
[INFO]  Generating a YAML configuration file and guessing the dependencies
  〜〜〜 省略 〜〜〜
[INFO]  Writing updates to configuration file (glide.yaml)
[INFO]  You can now edit the glide.yaml file.:
[INFO]  --> For more information on versions and ranges see https://glide.sh/docs/versions/
[INFO]  --> For details on additional metadata see https://glide.sh/docs/glide.yaml/

生成ファイルの確認

$ tree
.
├── cmd
│   └── main.go
├── glide.yaml
└── rootpackage.go

glide.yamlの中身

$ cat glide.yaml 
package: .
import:
- package: github.com/satori/go.uuid
  version: ~1.2.0
- package: github.com/sky0621/go-modules

依存パッケージのvendoring

$ glide up
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Fetching github.com/sky0621/go-modules
[INFO]  --> Fetching github.com/satori/go.uuid
[INFO]  --> Detected semantic version. Setting version for github.com/satori/go.uuid to v1.2.0
[INFO]  Resolving imports
[INFO]  Downloading dependencies. Please wait...
[INFO]  Setting references for remaining imports
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/sky0621/go-modules
[INFO]  --> Exporting github.com/satori/go.uuid
[INFO]  Replacing existing vendor dependencies
[INFO]  Project relies on 2 dependencies.

glide.lockが生成され、vendorディレクトリ配下に依存パッケージのソースが取得されている。

$ tree
.
├── cmd
│   └── main.go
├── glide.lock
├── glide.yaml
├── rootpackage.go
└── vendor
    └── github.com
        ├── satori
        │   └── go.uuid
        │       ├── LICENSE
        │       ├── README.md
        │       ├── codec.go
        │       ├── codec_test.go
        │       ├── generator.go
        │       ├── generator_test.go
        │       ├── sql.go
        │       ├── sql_test.go
        │       ├── uuid.go
        │       └── uuid_test.go
        └── sky0621
            └── go-modules
                ├── README.md
                ├── cmd
                │   └── main.go
                └── rootpackage.go

glide.lock

$ cat glide.lock 
hash: 450d4cce664d8e157d796b280456c6e33dbcf1a6529a42bd413a990516ba6bef
updated: 2018-11-19T01:58:50.856499847+09:00
imports:
- name: github.com/satori/go.uuid
  version: f58768cc1a7a7e77a3bd49e98cdd21419399b6a3
- name: github.com/sky0621/go-modules
  version: 4f5e5a5187c79413550655c9620d539923c65615
testImports: []

このファイルをソース管理しておけば、何かの拍子に依存関係の問題でビルドがこけても、正常だった頃に戻すことが可能。
glide.yamlだけだと(設定次第で)マイナーバージョンないしパッチバージョンはglide upを叩いた時点のバージョンに上がってしまうので、依存関係の修復が困難になるケースがある。

さて動作確認

GOPATH外でトライ

$ pwd
/tmp/go-modules/cmd
$
$ go run main.go 
main.go:8:2: cannot find package "github.com/satori/go.uuid" in any of:
    /home/koge/.goenv/versions/1.11.2/src/github.com/satori/go.uuid (from $GOROOT)
    /work/src/golang/src/github.com/satori/go.uuid (from $GOPATH)
main.go:6:2: no Go files in /work/src/golang/src/github.com/sky0621/go-modules

あれっ???
えーと、どうやら、glideではソースがGOPATH配下にないと、結局vendoringできない様子。
参照:https://qiita.com/mom0tomo/items/b66203b2718dd2626fd3#glideで何が問題になるのか-confused

GOPATH内でトライ

$ pwd
/work/src/golang/src/github.com/sky0621/go-modules/cmd
$
$ go run main.go 
Hello, World!
Bye!
UUIDv4: 46225e42-8129-47de-b284-146d16d7a948

いけた。
一応、GOPATH配下にmain.goでインポートしている「github.com/satori/go.uuid」が存在しないことは確認したけど、なんだか結局GOPATHに依存するのか。

試行ソースは下記。
https://github.com/sky0621/go-modules/tree/94e18719957dc74129667a0fb95b286e9169f08a

■Vendoring( dep )で依存パッケージ解決

depのインストールと適用

インストール

$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  〜〜〜 省略 〜〜〜
Setting executable permissions.
Moving executable to /work/src/golang/bin/dep

GOPATH外で適用

$ pwd
/tmp/go-modules
$
$ dep init
init failed: unable to detect the containing GOPATH: /tmp/go-modules is not within a known GOPATH/src

う〜ん、やっぱりdepGOPATH内でないとダメなのか。

GOPATH内で適用

$ pwd
/work/src/golang/src/github.com/sky0621/go-modules
$
$ dep init
  Using ^1.2.0 as constraint for direct dep github.com/satori/go.uuid
  Locking in v1.2.0 (f58768c) for direct dep github.com/satori/go.uuid

Gopkg.toml及びGopkg.lockが生成され、vendorディレクトリ配下に依存パッケージのソースが取得されている。

$ tree
.
├── Gopkg.lock
├── Gopkg.toml
├── cmd
│   └── main.go
├── rootpackage.go
└── vendor
    └── github.com
        └── satori
            └── go.uuid
                ├── LICENSE
                ├── README.md
                ├── codec.go
                ├── generator.go
                ├── sql.go
                └── uuid.go

さて、動作確認

$ pwd
/work/src/golang/src/github.com/sky0621/go-modules/cmd
$
$ go run main.go 
Hello, World!
Bye!
UUIDv4: b5e4a50f-b1bc-4044-8bc5-cea56d770992

試行ソースは下記。
https://github.com/sky0621/go-modules/tree/0e9b65282b80d3064528baf13c464e35e95bb573

まとめ

時間切れとなったので、Go moduleを試すのは、また次回。
ちなみに、実際にソース書いて試してというものではないけど、Goとバージョニングに関する歴史的な経緯も含めた情報はここに記載がある。(英語)
↑を翻訳したQiita記事もある。すごいね。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1