golang プロジェクト構成を考える


golangを使って色々と試したいなと思い調べていると、
どうもプロジェクト構成についてよく考えたほうが良さそうだった。

その時のメモとこれから随時、理解をしていきながら編集&更新していけたらと思う。
なので、ご指摘(できれば優しいアドバイスooo〜)ありましたらよろしくお願い致します。


まずは、

## GOPATH

GOPATHは任意のディレクトリを指定してもおｋ。
そして、PATHを通す。

```bash:.bash_profile
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
```
こちらは[公式](http://golang-jp.org/doc/install)やbrewでインストールした場合などに、
ファイルに書き込むことになるだろう。
(`$ echo $GOPATH`で、パスを確認。)

ただ、[gvm](https://github.com/moovweb/gvm)という、バージョン管理ツールをインストールすると、
上記の設定はgvmがやってくれるらしいので、そちらでも良さそう。
(`.bashrc`に自動読み込み。即反映するには、`$ source /home/ec2-user/.gvm/scripts/gvm`実行。)

## gvm

*  **gvm**をインストール

xcodeも必要になります。

```
$ brew install mercurial
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
```

*  **gvm**確認

```
$ gvm version
Go Version Manager v1.0.22 installed at /<Path>/<To>/.gvm
```

*  **gvm install**できるgolangのヴァージョンを確認

```
$ gvm listall
```

*  **gvm install**

```
$ gvm install go1.9.2
```
`-B`オプションでバイナリからインストール。

*  **gvm**でインストールした任意のヴァージョンを使う/切り替え

```
$ gvm use go1.9.2 --default
```
`--defaul`オプションで、terminalで再度ログインした後も指定したヴァージョンで使用できるようになる。

* goコマンドでヴァージョン確認

```
$ go version
go version go1.9.2 linux/amd64
```

*  **gvm**でインストールしたヴァージョン一覧を表示

```
$ gvm list
gvm gos (installed)

   go1.8.4
   go1.9.2
   system
```

*  **gvm**をアンインストール

```
$ gvm implode
```


## dep

依存関係管理(パッケージ管理)ツールです。
他のツールとしては、`glide`などがありますが、goの公式開発チームがサポートしているツールみたいなのでdepを使用してみた。

depを使用するメリットとして、他のプログラマーと開発する際、外部パッケージのヴァージョン管理が容易になります。
また、depを使用することで、`Gopkg.lock`、`Gopkg.toml`、`vendor/`ができあがります。
こちらの出来あがるファイルやディレクトリについては、後ほど。

*  **dep**をインストール

```
$ brew install dep
```

*  **dep**確認

```
$ dep version
dep:
 version     : devel
 build date  :
 git hash    :
.
.
.
```

一旦ここまで。
次は、プロジェクト構成を確認してから、depコマンドを使ってみます。


## プロジェクト構成

`GOPATH`配下にsrc、その配下にわかりやすいように`github.com/<ユーザー名>/`としてディレクトリを構成してみた。
下の構成でいうとgotest, gotest2がプロジェクトになります。
ソースコードは[こちら](https://qiita.com/ryutah/items/eff6a044c81c5ba109d0)の記事のものをサンプルプロジェクトとして使用させて頂きました。

```bash:directory1
$GOPATH
└── src
    └─ github.com
       │
       └── <UserName>
           ├── gotest
           └── gotest2
```

以下、`gotest`プロジェクトの構成

```bash:directory2
gotest/
|── Gopkg.lock
├── Gopkg.toml
├── Makefile
├── README.md
├── app
│   ├── app.yaml
│   └── main.go
├── gae
│   └── hello.go
└── vendor
    └── github.com
        ├── gorilla
        └── ryutah
```

ここで先ほどのdepで更新されるファイルがあるかと思います(Gopkg.lock、Gopkg.toml、vendor/)。
これらを作成していくので、プロジェクトディレクトリに移動して、以下を実行していく。
(glideからdepへの移行は、[こちら](https://qiita.com/spiegel-im-spiegel/items/e931ad1a7565d02d179e)の記事が非常に参考になりました!)


*  **dep init**を実行
Gopkg.lock、Gopkg.toml(編集可能)、vendor/を生成。

```
$ dep init
```
`-v`オプションで、ログを出力しながらinit。

*  **dep**でパッケージを追加&追記

例えば、main.goで定義してあるパッケージでインストールされてなければインストールされる。

```
$ dep ensure
$ dep ensure -add <PACKAGES>
```

*  **dep**でパッケージをアップデート

```
$ dep ensure -update <PACKAGES>
```

*  **dep**パッケージの状態を確認

```
$ dep status
```

# ローカルサーバーを立ち上げる

```bash
goapp serve -port <port num> app.yaml
```

エラーがでなければ完了です。


# おわり

gvmとdepでシンプルにプロジェクトを管理できるのかなと思います。
また、ghq+pecoでさらに可動性アップできそうです。


# トラブルシューティング

### GOPATHがなんか変わってた〜

---

gvmを利用するとgoの環境変数が勝手に書き換わります。
なので、設定ファイルを編集する必要があります。

設定ファイル自体は、`$HOME/.gvm/environments`配下にありました。

* 環境設定ファイルを作成

```bash
$ gvm pkgset create <name>
```

任意の名前を設定できる。私はわかりやすいように、`go<version>@<project name>`みたいにした。

* 編集

```
$ gvm pkgenv <name>
```

* 編集箇所

12行目と16行目。変更箇所のサンプルは以下。
プロジェクト名を追記していくかんじ。

```
# 12行目
export GOPATH; GOPATH="/Users/<mac user name>/.gvm/pkgsets/go1.9.2/gotest:$HOME/go:$GOPATH"

# 16行目
export PATH; PATH="/Users/<mac user name>/.gvm/pkgsets/go1.9.2/gotest/bin:${GVM_OVERLAY_PREFIX}/bin:$HOME/go/bin:${PATH}"
```

* プロジェクト毎にpkgsetファイルを切替

```bash
$ gvm pkgset use <name>
```

* pkgsetの一覧

```bash
$ gvm pkgset list
```

* GOPATHにコマンドで現在のディレクトリを追加

任意のプロジェクトディレクトリにて以下を実行。

```bash
$ gvm linkthis
```