| 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言語とそのライブラリやツールについての詳細な記事ひとそろいは、 ドキュメントページ を ご覧ください。