この記事はTumblrで公開されていました(Go 1.2の頃に書いたものです)
Go言語には、ワークスペースという構造があります。最初はとても取っ付きづらいのですが難しいものではないので、軽く書き流します。
ルール
GOROOT環境変数
GOROOT環境変数は、Go言語本体のファイルツリーを示します。~/go以下にインストールしたなら、GOROOTは~/goです。デフォルトはgoコマンドの親ディレクトリがGOROOT*と仮定されます。
go install
やgo get
コマンドは、$GOROOT/binまたは$GOROOT/pkgに、Go本体には含まれないコマンドやパッケージをインストールします*1。
GOPATH環境変数
GOPATH環境変数が設定されている場合、go install
やgo get
は、$GOPATH/binまたは$GOPATH/pkg以下を対象にコマンドやパッケージをインストールします。GOPATHが未設定ならGOROOTと同じ場所だと仮定されます。
$GOPATH以下は、次のような階層(ワークスペース)です。
$GOPATH/ bin/ (コマンドがインストールされる場所) pkg/ (コンパイルしたパッケージがインストールされる場所) src/ (ソースコードがインストールされる場所)
bin, pkgなどのディレクトリは必要に応じて作られるので、自分でディレクトリを作成する必要ありません。
Goコードの書き方
$GOPATH/src以下にプログラムを書いていくのですが、まずはリポジトリのURLを決めましょう。ここではgit@github.com:example/gointro.gitを使うとしました。
まずはcloneします。
$ export GOPATH=~/my $ cd $GOPATH $ mkdir -p src/github.com/example $ cd src/github.com/example $ git clone git@github.com:example/intro.git
適当にコードを書きます。
$ ed $GOPATH/src/github.com/example/intro/intro.go a package intro import "fmt" func Print() { fmt.Printf("test\n") } .
ひとつのpackageを構成するファイルを複数に分けることは自由ですし、サブディレクトリを作って、1つのリポジトリに複数パッケージを入れても構いません。
このパッケージを他プロジェクトから参照する場合は、$GOPATHからのパス表記をします。
package other import "github.com/example/intro" ...
ビルド時には、go get
コマンドがimportをみて、必要なパッケージを自動で取得してくれます。取得したパッケージは$GOPATHへインストールされます。
リポジトリにソースコードを置かない場合でも、$GOPATH/src直下にソースコードを書くのではなく、なんらかのディレクトリ以下へ入れて、なるべく不変にしたほうがいいです。というのも、import文は$GOPATHからの表記なので、後から変えるのが非常に大変です。
ワークスペースの運用
個人の感想ですが、GOROOTとGOPATHは分けた方が良いと思います。そうしないとGo本体とその他のファイルが混ざってわかりづらくなります。そのうえで、GOPATHは基本ひとつで運用したほうが楽なんじゃないかなあと思っています。理由は2つあって、
- $GOPATH/binにコマンドがインストールされるので、PATH追加が面倒
- 成果物はバイナリ1つで動作するため、混ざってもそれほど困らない
特に2つ目について、Goはネイティブコードにコンパイルする言語ですし、パッケージもバイナリにスタティックリンクするポリシー*2なのでワークスペースのパッケージをアップデートしたからといって、動いている環境に影響を与えることがありません*3。
なので、今の運用方法は基本的に以下の設定で行なっています。
export GOROOT=~/go export GOPATH=~/my
今のところ困っていませんが、どうしても分けたい場合はGOPATHを違う場所へ置き換えるつもりです。