お題
Go 1.11 における「Modules」は Go 1.12 での完成を目指す実験的なバージョン管理機能。
公式のwikiに従い、試してみよう。
開発環境
# OS
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="17.10 (Artful Aardvark)"
# Golang
$ go version
go version go1.11.2 linux/amd64
バージョンの切り替えはgoenvで行っている。
実践
■クイックスタートサンプルをトレース
1)GOPATH
外にプロジェクトを作成
$ env | grep GOPATH
GOPATH=/work/src/golang
$
$ mkdir -p /tmp/scratchpad/hello
$ cd /tmp/scratchpad/hello
2)Modulesの初期化
$ go mod init github.com/you/hello
go: creating new go.mod: module github.com/you/hello
go.mod
が出来る。
$ ll
-rw-r--r-- 1 koge koge 28 11月 19 09:30 go.mod
$
$ cat go.mod
module github.com/you/hello
3)外部パッケージのimportを含むソースを作成
$ cat <<EOF > hello.go
> package main
>
> import (
> "fmt"
> "rsc.io/quote"
> )
>
> func main() {
> fmt.Println(quote.Hello())
> }
> EOF
4)ビルド
$ go build
すると、実行ファイル「hello
」の他に、go.sum
というファイルも作られる。
$ ll
-rw-r--r-- 1 koge koge 57 11月 19 09:35 go.mod
-rw-r--r-- 1 koge koge 499 11月 19 09:35 go.sum
-rwxr-xr-x 1 koge koge 2.2M 11月 19 09:35 hello
-rw-r--r-- 1 koge koge 102 11月 19 09:33 hello.go
$ cat go.sum
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
そして、先ほどまではなかった「quote」パッケージに関する記述がgo.mod
に増えている。
go build
時に勝手にソースから依存パッケージを抽出してくれる様子。
$ cat go.mod
module github.com/you/hello
require rsc.io/quote v1.5.2
5)実行
$ ./hello
こんにちは世界。
■コンセプト
モジュール
「Modules」は関連するGoパッケージの集合であり、それらを1つの単位としてバージョニングしたもの。
目的は、依存関係を正確に記録しておき、再現可能なビルドを作成できるようにすること。
「Modules」はセマンティックバージョニングする必要がある。
先頭は「v」であり、「【メジャーバージョン】.【マイナーバージョン】.【パッチバージョン】」の形式である。
(例:「v0.1.0」、「v1.2.3」)
go.mod
モジュールは、あるディレクトリに「go.mod
」ファイルを持つGoソースのツリーとして定義される。
モジュールのソースコードは、GOPATH
の外部に配置されている必要がある。
モジュールの例:
module github.com/my/thing
require (
github.com/some/dependency v1.2.3
github.com/another/dependency/v4 v4.0.0
)
go.mod
には、「module」、「require」、「exclude」、「replace」の4つのディレクティブがある。
「module」は、そのモジュールを定義するパス。
「require」は、そのモジュール内のソースがimportする外部パッケージ。
「exclude」と「replace」は、メインモジュールをビルドする時に無視されるパッケージ。
例えば、「https://github.com/sky0621/go-modules」をgit clone
してモジュール化する場合、あらかじめ「【適当なパス】/github.com/sky0621
」というディレクトリを掘っておき、その下にgit clone
する。
それからそのプロジェクト内に移動してモジュール初期化。
$ cd go-modules/
$
$ pwd
/work/src/gomodule/github.com/sky0621/go-modules
$
$ go mod init github.com/sky0621/go-modules
go: creating new go.mod: module github.com/sky0621/go-modules
$
$ cat go.mod
module github.com/sky0621/go-modules
バージョンについて
Goのモジュールには従うべきルールがある。
- セマンティックバージョニングであること
- バージョン「v2」以上の場合はモジュールパスとimportパスに「v2」を含めること
- バージョン「v0」ないし「v1」の場合はモジュールパス、importパスにバージョンを含めないこと
■モジュールの使い方
インストール
以下参照。
アクティベート
以下いずれか。
- 環境変数「
GO111MODULE
」をアンセット後、GOPATH
以外のパスにgo.mod
ファイルを配置してgo
コマンド実行 - 「
GO111MODULE=on
」を環境変数にセットしてgo
コマンド実行
まとめ
だいぶ端折ったけど、ひとまず必要最低限は書いたかな。