Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
34
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

そろそろ真面目に Golang 開発環境について考える — Internal Packages と Vendoring

前回の続き。保留していた Go 1.5 の Vendoring 機能について。

今回の調査も含めて以下のパッケージを作った

spiegel-im-spiegel/gcatcat コマンド相当の機能を持つコマンドラインツールで,内部で spiegel-im-spiegel/gutil パッケージを呼んでいる。 spiegel-im-spiegel/gutil パッケージは雑多な処理を集めたものだが,まだ作りかけ。とりあえず spiegel-im-spiegel/gcat で使うものだけを置いている。

まずはこれを導入してみる。 spiegel-im-spiegel/gutil を submodule にしてるのでちょっとウザいけどご勘弁を。あと,ユーザ名が長いのはホンマごめん。こんなことならもっと短い名前にするんだった。

C:>mkdir C:\workspace\gcat

C:>cd C:\workspace\gcat

C:\workspace\gcat>SET GO15VENDOREXPERIMENT=1

C:\workspace\gcat>SET GOPATH=C:\workspace\gcat

C:\workspace\gcat>go get -d github.com/spiegel-im-spiegel/gcat
# cd .; git --git-dir=C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gcat/.git submodule update --init --recursive
No submodule mapping found in .gitmodules for path 'vendor/github.com/spiegel-im-spiegel/gutil'
package github.com/spiegel-im-spiegel/gcat: exit status 1

C:\workspace\gcat>pushd src\github.com\spiegel-im-spiegel\gcat

C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gcat>git submodule init
Submodule 'vendor/github.com/spiegel-im-spiegel/gutil' (https://github.com/spiegel-im-spiegel/gutil.git) registered for path 'vendor/github.com/spiegel-im-spiegel/gutil'

C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gcat>git submodule update
Cloning into 'vendor/github.com/spiegel-im-spiegel/gutil'...
remote: Counting objects: 25, done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 25 (delta 10), reused 15 (delta 4), pack-reused 0
Unpacking objects: 100% (25/25), done.
Checking connectivity... done.
Submodule path 'vendor/github.com/spiegel-im-spiegel/gutil': checked out '7d271650d9937ef0e7b447aff5a55f410f2c9f89'

C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gcat>popd

C:\workspace\gcat>go install -v ./...
github.com/spiegel-im-spiegel/gcat/vendor/github.com/spiegel-im-spiegel/gutil
github.com/spiegel-im-spiegel/gcat/internal/gcat
github.com/spiegel-im-spiegel/gcat/internal/facade
github.com/spiegel-im-spiegel/gcat

C:\workspace\gcat>echo Take the Go-lang! | bin\gcat.exe
Take the Go-lang!

導入時のフォルダ構成はこうなっている。

C:\workspace\gcat>tree .
C:\WORKSPACE\GCAT
├─bin
├─pkg
│  └─windows_amd64
│      └─github.com
│          └─spiegel-im-spiegel
│              └─gcat
│                  ├─internal
│                  └─vendor
│                      └─github.com
│                          └─spiegel-im-spiegel
└─src
    └─github.com
        └─spiegel-im-spiegel
            └─gcat
                ├─internal
                │  ├─facade
                │  └─gcat
                └─vendor
                    └─github.com
                        └─spiegel-im-spiegel
                            └─gutil

このフォルダ構成に対して main.go の記述は以下のとおりである。

main.go
package main

import (
    "os"

    "github.com/spiegel-im-spiegel/gcat/internal/facade"
    "github.com/spiegel-im-spiegel/gutil"
)

func main() {
    cli := &gutil.CliContext{Reader: os.Stdin, Writer: os.Stdout, ErrorWriter: os.Stderr}
    facadeCxt := &facade.Context{Cli: cli, CommandName: Name, Version: Version}
    os.Exit(facadeCxt.Run(os.Args))
}

ポイントになるのは internal フォルダと vendor フォルダだ。もう少し詳しく見ていこう。

パッケージ外部からの呼び出しを禁止する Internal Packages

Internal Packages の仕組みは 1.4 のころから存在したが, 1.5 から GOPATH 配下のパッケージまで拡張された。

要するに internal フォルダ以下のパッケージは外部から参照できない。これは再利用の難しいビジネスロジックを含むパッケージを配置する場合にはよい仕掛けである。 Internal Packages の制約から外すには internal フォルダの外側にパッケージを再配置すればよい。

Vendoring 機能

環境変数 GO15VENDOREXPERIMENT に 1 をセットすると Go 1.5 の Vendoring 機能が使える。

追記 当初の予告通り Vendoring 機能は 1.6 から既定の機能になった。環境変数 GO15VENDOREXPERIMENT をセットしなくても有効になる)

Vendoring 機能が有効な状態では vendor フォルダが特別な意味を持つ。たとえば mypackage パッケージに対して mypackage/vendor/vpackage と配置した場合, import "vpackage" と記述すれば mypackage/vendor フォルダ以下の vpackage を探してくれる。上述の spiegel-im-spiegel/gcat の場合は github.com/spiegel-im-spiegel/gutil がこれにあたり,実体は github.com/spiegel-im-spiegel/gcat/vendor/github.com/spiegel-im-spiegel/gutil にある。パッケージが見つからない場合は

C:\workspace\gcat>go install -v ./...
src\github.com\spiegel-im-spiegel\gcat\internal\gcat\catenate.go:4:2: cannot find package "github.com/spiegel-im-spiegel/gutil" in any of:
        C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gcat\vendor\github.com\spiegel-im-spiegel\gutil (vendor tree)
        C:\Go\src\github.com\spiegel-im-spiegel\gutil (from $GOROOT)
        C:\workspace\gcat\src\github.com\spiegel-im-spiegel\gutil (from $GOPATH)

という感じのエラーになり, Vendor tree → GOROOTGOPATH の順でパッケージを探していることが分かる。

ただしこの Vendoring 機能は実験段階であり,上手くいけば次かその次のバージョンでは既定で有効になるようだが,当面は様子見というところだろうか。

ブックマーク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
34
Help us understand the problem. What are the problem?