Goのコード構成についての公式ドキュメントの日本語翻訳

この記事はGo言語の公式ドキュメント" How to Write Go Code"の一部を自己学習のために翻訳したものです。

## コード構成(Code organization)

### 全体(Overview)

- Go言語はすべてのコードを一つの「ワークスペース」で管理しています。
- ワークスペースは複数のVCSリポジトリを含んでいる
- それぞれのリポジトリは一つあるいは複数のパッケージを格納しています。
- それぞれのパッケージは単一のディレクトリ中の一つあるいは複数のGoのソースファイルから構成されています。
- パッケージのディレクトリについてのパスは`import path`を定義しています。

## ワークスペース(Workspaces)

ワークスペースはルートに二つのディレクトリを持つ、ディレクトリの階層構造です。

- `src`はGoのソースファイルを格納しています。
- `bin`は実行可能なコマンドを格納しています。

`go`ツールはビルドの実行および`bin`ディレクトリへのインストールを行います。

`src`ディレクトリは一般的に複数の(GitやMercurialのような)バージョン管理リポジトリを含んでおり、単一あるいはそれ以上のソースパッケージの開発をトラッキングします。

ワークスペースが実際にどのようなものかを理解していただくための例がこちらです。

```
bin/
    hello                          # command executable
    outyet                         # command executable
src/
    github.com/golang/example/
        .git/                      # Git repository metadata
	hello/
	    hello.go               # command source
	outyet/
	    main.go                # command source
	    main_test.go           # test source
	stringutil/
	    reverse.go             # package source
	    reverse_test.go        # test source
    golang.org/x/image/
        .git/                      # Git repository metadata
	bmp/
	    reader.go              # package source
	    writer.go              # package source
    ... (many more repositories and packages omitted) ...
```

上記のツリーはワークスペースが(`example`と`image`の)二つのリポジトリを保持していることを示しています。

`example`リポジトリは二つのコマンド(`hello`と`outyet`)と一つのライブラリ(`stringutil`)を保持しています。

また`image`リポジトリは`bmp`パッケージと[いくつか別のもの](https://godoc.org/golang.org/x/image)を保持しています。

一般的なワークスペースはいくつものパッケージとコマンドが含まれた複数のソースリポジトリを格納しています。

多くのGoのプログラマはGoのソースコードとDependenciesを単一のワークスペースに保持しています。

注釈しておくと、シンボリックリンクはファイルとディレクトリをワークスペースに関連づけるために**使うべきではありません**。

コマンドとライブラリは異なるソースパッケージからビルドされます。この違いに関しては[後ほど](https://golang.org/doc/code.html#PackageNames)お話しします。

## `GOPATH`環境変数(The GOPATH environment variable)

GOPATH環境変数はあなたのワークスペースの場所を明示します。

それはあなたのホームディレクトリ中の`go`と命名されているディレクトリをデフォルトに設定します、なのでUnixでは`$HOME/go`、Plan 9では`$home/go`、そしてWindowsでは`%USERPROFILE%\go`(一般的には`C:\Users\YourName\go`)となっています。

もしあなたが異なる場所で作業したい場合、そのディレクトリのパスへ[GOPATHを設定する](https://golang.org/wiki/SettingGOPATH)必要があります(他の共通的なセットアップは`GOPATH=$HOME`へ設定することです)。

GOPATHはGoがインストールされている場所と**同一にしてはいけない**点に注意してください。

`go env GOPATH`コマンドは現在の実際のGOPATHを表示してくれます。もし環境変数が設定されていない場合はデフォルトの場所を示してくれます。

利便性のためにワークスペースの`bin`サブディレクトリをあなたのPATHに追加しましょう:

```
$ export PATH=$PATH:$(go env GOPATH)/bin
```

本ドキュメントにおけるスクリプトは簡潔さのために`$(go env GOPATH)の代わりに`$GOPATH`を用います。

To make the scripts run as written if you have not set GOPATH, you can substitute $HOME/go in those commands or else run: 

```
$ export GOPATH=$(go env GOPATH)
```

GOPATH環境変数にさらに学ぶためには、[go help gopath](https://golang.org/cmd/go/#hdr-GOPATH_environment_variable)を参照してください。

独自のワークスペースの場所を利用するためには、[GOPATH環境変数を設定する](https://golang.org/wiki/SettingGOPATH)を参照。

## インボートパス(Import paths)

`import path`は独自にパッケージを識別するための文字列です。パッケージのインボートパスはワークスペースあるいはリモートリポジトリの場所に対応します(後ほど説明します)。

スタンダードライブラリ由来のパッケージは"fmt"や"net/http"のように短縮されたインポートバスが与えられています。

あなたの独自のパッケージについては、将来的なスタンダードライブラリあるいは別の外部ライブラリと衝突しないようなベースパスを選択しなければいけません。

もしあなたのコードをどこかのソースリポジトリに保持したい場合、ソースリポジトリのルートをベースパスとして設定すべきです。例えばあなたが`github.com/user`というGitHubアカウントを持っていた場合、それがあなたのベースパスとなるべきということです。

ビルドができるようになる前にリモートリポジトリにあなたのソースコードを公開する必要はないことを注釈しておきます。

これはあなたがコードをいつか公開することになることになった場合、コードを構成するのにちょうどいい習慣になります。

実際にはスタンダートライブラリやGoのエコシステムに対してパス名が独自である限り、あなたは適当なパス名を選択することができます。

`github.com/user`を私たちのベースパスとして使うことにします。あなたのワークスペース内部でソースコードを保持するディレクトリを作成してください。

```
$ mkdir -p $GOPATH/src/github.com/user
```

## あなたの最初のプログラム(Your first program)

簡単なプログラムのコンパイルと実行を行うために、まずパッケージパスを選択しましょう(私たちは`github.com/user/hello`を使います)。そして対応するパッケージディレクトリをワークスペース内部に作成します。

```
$ mkdir $GOPATH/src/github.com/user/hello
```

次に以下のコードを含んだ`hello.go`という名前のファイルをディレクトリ内部に作成します。

```go

package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}
```

今あなたはこのプログラムを`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`として)。

私たちの例では、それは`$HOME/go/bin/hello`である`$GOPATH/bin/hello`となります。

`go`ツールはエラーが発生した場合、アウトプットのみを表示します。そのためそれらのコマンドは正常に実行された場合何も出力を生成しません。

今あなたはコマンドラインにてフルパスを入力することで、プログラムを実行できます。

```
$ $GOPATH/bin/hello
Hello, world.
```

あるいは`$GOPATH/bin`をPATHに追加していれば、バイナリ名のみを入力すれば良いです。

```
$ hello
Hello, world.
```

もしあなたがソース管理システムを利用している場合、今がリポジトリのイニシャライズ、ファイルの追加、そして最初の変更をコミットする良いタイミングでしょう。

もう一度言うと、これは任意のステップです。あなたはGoのコードを書くためにソース管理を利用する必要はありません。

## あなたの最初のライブラリ(Your first library)

ライブラリを書いて`hello`プログラムから利用してみましょう。

再度申し上げると、最初のステップはパッケージパス(私たちは`github.com/user/stringutil`を利用します)を選択し、パッケージディレクトリを作成することです。

```
$ mkdir $GOPATH/src/github.com/user/stringutil
```

次にディレクトリ内で次のコンテンツを持った`reverse.go`という名前のファイルを作成しましょう。

```go
// Package stringutil contains utility functions for working with strings.
package stringutil

// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
	r := []rune(s)
	for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
		r[i], r[j] = r[j], r[i]
	}
	return string(r)
}
```

では`go build`でパッケージのコンパイルを試してみましょう。

```
$ go build github.com/user/stringutil
```

あるいは、もしあなたがパッケージのソースディレクトリで作業している場合は単純に、

```
$ go build
```

これは出力ファイルを生成しません。代わりにコンパイルされたパッケージをローカルのビルドキャッシュに保存します。

`stringutil`パッケージのビルドを確認したら、それを使うようにあなたの元々の`hello.go`(`$GOPATH/src/github.com/user/hello`にある)を変更しましょう。

```golang

package main

import (
	"fmt"

	"github.com/user/stringutil"
)

func main() {
	fmt.Println(stringutil.Reverse("!oG ,olleH"))
}

```

`hello`プログラムをインストールしてください。

```
$ go install github.com/user/hello
```

新しいバージョンのプログラムを実行しましょう、あなたは新しい、反転されたメッセージを見るはずです。

```
$ hello
Hello, Go!
```

上記のステップを踏んだ後、あなたのワークスペースはこのようになっているはずです:

```
bin/
    hello                 # command executable
src/
    github.com/user/
        hello/
            hello.go      # command source
        stringutil/
            reverse.go    # package source
```

## パッケージ名(Package names) 

第一のステートメントとして、Goのソースファイルは必ず次のようになっている必要があります。

```go

package name
```

`name`はインポートのためのパッケージのデフォルト名です(すべてのパッケージ中のファイルは同一の`name`を使っている必要があります)。

Goの規約として、パッケージ名はインポートパスの最後の要素であるというのがあります。`crypto/rot13`としてインポートされるパッケージは`rot13`として命名されるべきです。

実行可能なコマンドは常に`package main`を使わなければなりません。

パッケージ名は単一のバイナリに紐づくすべてのパッケージにおいてユニークである必要はありません。ただインポートパス(それらのフルファイル名)のみがユニークです。

Goの命名規則についてより学ぶために、[効率的なGo](https://golang.org/doc/effective_go.html#names)を参照してください。

## 所感

Goの単一管理するワークスペースという概念は独特で面白いですね。

このドキュメントでは発展的なコードを書くわけではありませんが、基本的なGoの概念を学ぶには良いなと思いました。

## 翻訳元

https://golang.org/doc/code.html