Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

Goワークスペース

この記事はTumblrで公開されていました(Go 1.2の頃に書いたものです)

Go言語には、ワークスペースという構造があります。最初はとても取っ付きづらいのですが難しいものではないので、軽く書き流します。

ルール

GOROOT環境変数

GOROOT環境変数は、Go言語本体のファイルツリーを示します。~/go以下にインストールしたなら、GOROOT~/goです。デフォルトはgoコマンドの親ディレクトリがGOROOT*と仮定されます。

go installgo getコマンドは、$GOROOT/binまたは$GOROOT/pkgに、Go本体には含まれないコマンドやパッケージをインストールします*1

GOPATH環境変数

GOPATH環境変数が設定されている場合、go installgo 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からの表記なので、後から変えるのが非常に大変です。

ワークスペースの運用

個人の感想ですが、GOROOTGOPATHは分けた方が良いと思います。そうしないとGo本体とその他のファイルが混ざってわかりづらくなります。そのうえで、GOPATHは基本ひとつで運用したほうが楽なんじゃないかなあと思っています。理由は2つあって、

  • $GOPATH/binにコマンドがインストールされるので、PATH追加が面倒
  • 成果物はバイナリ1つで動作するため、混ざってもそれほど困らない

特に2つ目について、Goはネイティブコードにコンパイルする言語ですし、パッケージもバイナリにスタティックリンクするポリシー*2なのでワークスペースのパッケージをアップデートしたからといって、動いている環境に影響を与えることがありません*3

なので、今の運用方法は基本的に以下の設定で行なっています。

export GOROOT=~/go
export GOPATH=~/my

今のところ困っていませんが、どうしても分けたい場合はGOPATHを違う場所へ置き換えるつもりです。

*1:パッケージとは、だいたいライブラリのことですね

*2:このポリシーはPlan 9 Cコンパイラから変わっていないので、今後も変わらないでしょう

*3:他の言語だと、いわゆるDLL HELLが起こる可能性がありますね