オレオレGo入門2016

自分が Go で誰かと何か作るなら、まずここまでを共有してからにしたい、という勝手な理由ですぐ見てもらえるところにこれ置いときます。

## ディレクトリ

[How to Write Go Code](https://golang.org/doc/code.html) を読みましょう。ただし、これだけでは `src` の下に依存パッケージ置き場 `vendor` を置けることに言及してないので、Gopher Academuy Blog の [Understanding and using the vendor folder](https://blog.gopheracademy.com/advent-2015/vendor-folder/) で補うのが手っ取り早いです。

そのうえで、 [Glide | Package Management For Go](https://glide.sh/) を使いましょう。チームメンバーに足りないパッケージをコツコツ `$GOPATH/src/github.com/` に `go get` させず、チームが決めた依存パッケージが自動的に `vendor` にインストールされるようにしましょう。

```
/.../your/workspace/
  bin/
  pkg/
    darwin_amd64/
  src/
    your/product/
      .git
      main.go
      glide.yml
      vendor/
        github.com/
        gopkg.in/
```

一般的には、 **異なるパッケージは個別にバージョン管理されるべき** です。あなたは `src` に自分のパッケージ以外に、同僚のパッケージを置くかもしれません。チームメンバーの中には、あなたのパッケージを `src` 下に置いて再利用したい人がいるかもしれません。

インハウスなソフトウェアの場合は、パッケージ名をかならずしも `github.com/...` (のようなホスティングサービスのURL) で始める必要はないものとします。(GitHub で)パッケージを公開するとはかぎらないからです。とはいえユニークな名前空間を設けるのは必須です。

## GOPATH

個人的に使いたいGoツールのために自分用の `$GOPATH` を決めましょう。これとワークスペースの `$GOPATH` とは別のものにします。

```shell-session
export GOPATH=$HOME/.go
export PATH=$HOME/.go/bin:$PATH
```

ワークスペースで作業するときは、第二の `$GOPATH` を追加します。`your/workspace/bin` にインストールしたプロジェクトワークスペース固有のコマンドを使うかもしれません。

```shell-session
cd your/workspace
export GOPATH=`pwd`:$GOPATH
export PATH=`pwd`/bin:$PATH
```

 このとき [kennethreitz/autoenv: Directory-based environments.](https://github.com/kennethreitz/autoenv) が役に立つかもしれません。

## IDE

複数のパッケージにまたがる開発の場合、パッケージ境界を明確に分けましょう。 分けられるのであれば、IDE プロジェクトのルートを `$GOPATH` ではなく個々のパッケージにします。

`$GOPATH` は複数のパッケージを収める作業場所です。IDE のフォルダツリーのルートが `$GOPATH` だと、`src` の下階層が無駄に深くなります。

IntelliJ IDEA にはひとつのプロジェクトに複数のモジュールを定義できます。Eclipse は起動時にワークスペースを選択でき、その配下に複数のプロジェクトを置けます。(そんなに詳しくないんで合ってるかな)

PhpStorm など複数コンテキストが苦手な IDE の場合は、2016.3 で追加されるこの機能が役に立つかもしれません: [Opening Many Project in One Frame | PhpStorm Blog](https://blog.jetbrains.com/phpstorm/2016/11/opening-many-project-in-one-frame/)

## Docker

Mac/Windows で開発している人は、Linux にデプロイする前に [Docker for Mac](https://docs.docker.com/docker-for-mac/)/[Windows](https://docs.docker.com/docker-for-mac/) と [Docker標準のGo言語イメージ](https://hub.docker.com/_/golang/) を使って Linux バイナリとしての挙動を確認します。

公式イメージは、ファイルシステムのトップレベルに `/go` があり、`$GOPATH` となっています。また、そこがカレントディレクトリで始まります。`src` だけ (もしくは関係あるパッケージのディレクトリとその `vendor`) をホストと共有することで、 でバイナリの格納フォルダは分離できます。


```
/
  go/     # WORKDIR がここで $GOPATH もここ
    bin/  # ここはコンテナ固有のファイルが入る
    src/  # ホストと共有
```

まずは対話的にツールを試し、自動化していてわからなくなったら、いつでもここに戻って来れるようにしましょう。

```shell-session
$ docker run -v your/workspace/src:/go/src -it golang                                                
root@8ac8d75a8aae:/go# pwd
/go
root@8ac8d75a8aae:/go# ls
bin  src
root@8ac8d75a8aae:/go# go run src/....
```

決まったことを何度も行うときは `--rm` を付け、自分のプロセス終了と同時にコンテナを消すようにしましょう。(対話シェルでも `--rm` やるべきかも)

```shell-session
$ docker run -v your/workspace/src:/go/src -p 8080:8080 \
-it --rm golang go run src/your/package/main.go
```

docker-compose で同じことを再現できるようにしておきましょう。

```yaml
version: 2
services:
  service1:
    image: golang
    command: go run src/your/package/main.go
    volumes:
      - your/workspace/src:/go/src
    ports:
      - 8080:8080
  service2:
      :
      :  
```