Version: | Build version go 1.1.1 |
---|---|
original: | http://golang.org/doc/code.html |
Contents
このドキュメントではシンプルなGoパッケージの開発を実際にやってみて、Goパッケージや コマンドをフェッチ、ビルド、およびインストールする標準的な方法である goツール を紹介 します。
goツールは、あなたのコードが指定の方法で整理されている必要があります。 このドキュメントを注意深く読んでください。Goのインストレーションを組み上げ、実行する ための最も簡単な方法を説明しています。
同様の説明が スクリーンキャスト として利用可能です。
Goツールは公開リポジトリでメンテナンスされているオープンソースコードで動作するように 設計されています。あなたのコードを公開する必要はありませんが、環境の設定方法のモデル はコードを公開してもしなくても同様に動作します。
Goコードはワークスペース内に保存する必要があります。ワークスペースは、ルートに3つの ディレクトリを持つディレクトリ階層です:
src
はパッケージ単位(1ディレクトリ毎に1パッケージ)に整理されたGoソースファイルを、pkg
はパッケージオブジェクトを、そしてbin
は実行可能なコマンドを含みます。
Goツールはソースパッケージをビルドして pkg
と bin
ディレクトリに結果のバイナリを
インストールします。
src
サブディレクトリは通常、1つまたは複数のソースパッケージの開発を追跡する、
複数の(GitやMercurialのような)バージョン管理リポジトリを含んでいます。
実際のワークスペースがどのようなものかが分かるように、例を示します:
bin/ streak # command executable todo # command executable pkg/ linux_amd64/ code.google.com/p/goauth2/ oauth.a # package object github.com/nf/todo/ task.a # package object src/ code.google.com/p/goauth2/ .hg/ # mercurial repository metadata oauth/ oauth.go # package source oauth_test.go # test source github.com/nf/ streak/ .git/ # git repository metadata oauth.go # command source streak.go # command source todo/ .git/ # git repository metadata task/ task.go # package source todo.go # command source
このワークスペースは、2つのコマンド(streak
, todo
)と2つのライブラリ
(oauth
, task
)を含む、3つのリポジトリ(goauth2
, streak
および
todo
)が含まれています。
コマンドとライブラリは異なる種類のソースパッケージからビルドされます。区別については 後で 説明します。
GOPATH 環境変数はワークスペースの場所を指定します。これは恐らくGoコードを開発する ときにだけ設定する必要がある環境変数です。
まずはじめにワークスペースのディレクトリを作成し、それに応じてGOPATHを設定します。 ワークスペースは好きな場所に配置できますが、このドキュメントでは$HOME/goを使用します。 これはGoのインストレーションと同じパスであってはいけないことに注意してください。
$ mkdir -p $HOME/go $ export GOPATH=$HOME/go
便宜的に、ワークスペースの bin
サブディレクトリをPATHに追加します:
$ export PATH=$PATH:$GOPATH/bin
標準ライブラリのパッケージには、"fmt"や"net/http"などの短いパスを与えられています。 独自のパッケージでは、標準ライブラリへの将来の追加や他の外部ライブラリとまず衝突する ことのないベースパスを選択する必要があります。
あなたがどこかのソースリポジトリにコードを保管しているのなら、ベースパスとしてその
ソースリポジトリのルートを使う必要があります。例えば github.com/user
という
Github アカウントを持っている場合は、それがベースパスであるべきです。
ビルドができるよりも前にリモートリポジトリにコードを公開する必要はない、ということに 注意してください。ただ、いずれは公開するつもりでコードを整理しておくのは良い習慣です。 実際には、標準ライブラリと、より大きなGoエコシステムに於いてユニークである限りは、 任意のパス名を選択できます。
私たちはベースパスとして github.com/user
を使用します。
ワークスペースの中にソースコードを保存するディレクトリを作りましょう:
$ mkdir -p $GOPATH/src/github.com/user
簡単なプログラムをコンパイルして実行するには、まずパッケージパス(ここでは
github.com/user/hello
を使用します)を選択し、ワークスペース内に対応する
パッケージディレクトリを作成します:
$ mkdir $GOPATH/src/github.com/user/hello
次に、以下のGoコードを含む hello.go
という名前のファイルをディレクトリの中に
作成します:
package main import "fmt" func main() { fmt.Printf("Hello, world.\n") }
goツールを使ってそのプログラムをビルドし、インストールできます:
$ go install github.com/user/hello
システム上のどこからでも、このコマンドを実行できることに注意してください。goツールは GOPATHによって指定されたワークスペース内の github.com/user/hello を探してソースコードを 見つけます。
パッケージディレクトリからgo installを実行する場合は、パッケージのパスを省略できます:
$ cd $GOPATH/src/github.com/user/hello $ go install
このコマンドは hello
コマンドをビルドし、実行可能なバイナリを提供します。その後、
ワークスペースの bin
ディレクトリにそのバイナリを hello
(Windows環境では
hello.exe
) としてインストールします。この例では、 $GOPATH/bin/hello
つまり、
$HOME/go/bin/hello
になります。
goツールはエラーが発生した時だけ出力するので、これらのコマンドが何も出力しない場合には、 これらは正常に実行されています。
これで、コマンドラインで完全なパスを入力してプログラムを実行できます:
$ $GOPATH/bin/hello Hello, world.
もしくは、 $GOPATH/bin
をPATHに追加してあるなら、単にバイナリ名を入力します:
$ hello Hello, world.
もしソース管理システムを使っているなら、今がリポジトリを初期化して、ファイルを追加し、 最初の変更をコミットするのに良い時でしょう。
繰り返しますが、この手順はオプションです: Goコードを書くのにソース管理を使う必要は ありません。
$ cd $GOPATH/src/github.com/user/hello $ git init Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/ $ git add hello.go $ git commit -m "initial commit" [master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.go
リモートリポジトリへのコードのプッシュは、読者の練習として残しておきます。
ライブラリを書いて hello
プログラムからそれを使ってみましょう。
繰り返しになりますが、最初の手順はパッケージのパス(ここでは github.com/user/newmath
を使います)を選択して、パッケージのディレクトリを作成することです:
$ mkdir $GOPATH/src/github.com/user/newmath
次に、以下の内容で、そのディレクトリに sqrt.go
という名前のファイルを作成します。
// Package newmath is a trivial example package. package newmath // Sqrt returns an approximation to the square root of x. func Sqrt(x float64) float64 { z := 1.0 for i := 0; i < 1000; i++ { z -= (z*z - x) / (2 * z) } return z }
さて、 go build
でそのパッケージのコンパイルを試します:
$ go build github.com/user/newmath
またはパッケージのソースディレクトリで作業をしているなら、単に:
$ go build
これは出力ファイルを生成しません。ワークスペースの pkg
ディレクトリ内にパッケージ
オブジェクトを配置するためには、 go install
を使わなければなりません。
newmathパッケージがビルドされたことを確認したあと、それを使用するために、オリジナルの
($GOPATH/src/github.com/user/hello にある) hello.go
を変更します:
package main import ( "fmt" "github.com/user/newmath" ) func main() { fmt.Printf("Hello, world. Sqrt(2) = %v\n", newmath.Sqrt(2)) }
goツールはパッケージやバイナリをインストールするたびに、それが持つあらゆる依存関係も
インストールします。そのため hello
プログラムをインストールするときには:
$ go install github.com/user/hello
newmathパッケージも同様に、自動的にインストールされます。
プログラムの新しいバージョンを実行すると、いくつか数値の出力が目に付くでしょう:
$ hello Hello, world. Sqrt(2) = 1.414213562373095
上記の手順の後、ワークスペースは次のようになります。
bin/ hello # command executable pkg/ linux_amd64/ # this will reflect your OS and architecture github.com/user/ newmath.a # package object src/ github.com/user/ hello/ hello.go # command source newmath/ sqrt.go # package source
go installがnewmath.aオブジェクトを、そのソースディレクトリをそっくり映した
pkg/linux_amd64
ディレクトリに配置していることに注意してください。これはgo toolの
将来の呼び出しがパッケージオブジェクトを見つけて、パッケージの不必要な再コンパイルを
避けることができるようにするためです。 linux_amd64
の部分は、クロスコンパイルを
支援するためにあり、あなたのシステムのオペレーティングシステムとアーキテクチャに
反映されます。
Goコマンド実行可能ファイルは静的にリンクされています; パッケージオブジェクトはGoの プログラムを実行するために存在する必要はありません。
Goソースファイルの最初の行は
package name
となり、 name はインポートのためのパッケージのデフォルトの名前でなければなりません。 (パッケージ内の全てのファイルは同じ名前を使用しなければなりません。)
Goの規約では、パッケージ名はインポートパスの最後の要素になります: "crypto/rot13"として インポートされるパッケージは"rot13"という名前を付ける必要があります。
実行可能コマンドは、常にパッケージ main
を使わなければなりません。
パッケージ名は、単一のバイナリにリンクされている全てのパッケージの中で一意である必要は なく、ただ1つインポートパス(それらの完全なファイル名)が一意であることが要件です。
Goの命名規則について詳細を知るためには、 Effective Go を参照してください
Goはgo testコマンドと testing
パッケージで構成される軽量のテストフレームワークを
持っています。
func (t *testing.T)
シグネチャを持つ TestXXX
という名前の関数を含んだ、
_test.go
で終わる名前のファイルを作成して、テストを書きます。テストフレームワークでは
そのような関数を実行します; もし関数が t.Error
や t.Fail
のような障害関数を
呼び出した場合、そのテストは失敗したと見做されます。
以下のGoコードを含むファイル $GOPATH/src/github.com/user/newmath/sqrt_test.go
を
作成してnewmathパッケージにテストを追加しましょう。
package newmath import "testing" func TestSqrt(t *testing.T) { const in, out = 4, 2 if x := Sqrt(in); x != out { t.Errorf("Sqrt(%v) = %v, want %v", in, x, out) } }
そうしたら、go testでテストを実行します:
$ go test github.com/user/newmath ok github.com/user/newmath 0.165s
いつものように、パッケージディレクトリからgoツールを実行している場合は、パッケージパスを 省略できます:
$ go test ok github.com/user/newmath 0.165s
詳しいことについては、 go help test を実行して testingパッケージドキュメント を 参照してください。
インポートパスは、GitやMercurialのようなバージョン管理システムを使用してパッケージの ソースコードを取得する方法を記述することができます。goツールはリモートリポジトリから 自動的にパッケージを取得するために、このプロパティを使用しています。 例えば、本ドキュメントに記載されている例はGoogle Code code.google.com/p/go.example に ホストされたMercurialリポジトリに保管されています。もしあなたがパッケージのインポート パスにリポジトリのURLを含めているなら、go getはそれを自動的に取得して、ビルドし、そして インストールします:
$ go get code.google.com/p/go.example/hello $ $GOPATH/bin/hello Hello, world. Sqrt(2) = 1.414213562373095
指定されたパッケージがワークスペース内に存在しない場合、go getはまずGOPATHで指定された ワークスペース内に配置します(パッケージが既に存在する場合、go getはリモートの取得を スキップし、go installと同じ様に振る舞います)。
上記のgo getコマンドを発行した後、ワークスペースのディレクトリツリーは次のようになります:
bin/ hello # command executable pkg/ linux_amd64/ code.google.com/p/go.example/ newmath.a # package object github.com/user/ newmath.a # package object src/ code.google.com/p/go.example/ hello/ hello.go # command source newmath/ sqrt.go # package source sqrt_test.go # test source github.com/user/ hello/ hello.go # command source newmath/ sqrt.go # package source sqrt_test.go # test source
Google Codeでホストされている hello
コマンドは、同じリポジトリ内のnewmathパッケージに
依存しています。 hello.go
ファイルの中のインポートは、同じインポートパス規則を使って
いるので、go getコマンドは依存するパッケージも見つけてインストールすることもできます。
import "code.google.com/p/go.example/newmath"
この規則は、あなたのGoパッケージを他の人が利用可能にするための最も簡単な方法です。 Go Wiki と godoc.org では外部のGoプロジェクトの一覧を提供しています。
goツールを使ったリモートリポジトリの利用に関する詳細については、 go help remote を 参照してください。
わかり易く、慣用的なGoコードを書く上でのヒントは、 Effective Go を参照してください。
言語をきちんと学習するには A tour of Go をやりましょう。
Go言語とそのライブラリやツールについての詳細な記事ひとそろいは、 ドキュメントページ を ご覧ください。