オープンソースこねこね

Webプログラミングなどについてあれこれ。

Goの開発環境

最近Go言語をいじっているので、現時点での開発環境についてまとめておく。ツールを先に列挙しておくと以下のものを使っている。

エディタ

Sublime Text3を使っている。普段PHPを書くのに使っていて慣れているからであって最適だとは思ってはいない(静的型言語はIDEを使う方がいいとは思っているのだが、ショートカットキーを新たに覚えたりするのがつらいので使い続けている)。

これにGo用のプラグインGo​Sublimeをインストールしている。

また関数定義などにジャンプするためにctagsも使っている。ctags自体はhomebrewでインストールして、SublimeにはCtagsプラグインを入れている。標準だとctagsはGoに対応していないのだが

go - ctag database for golang - Stack Overflow

にあるように、~/.ctags

--langdef=Go
--langmap=Go:.go
--regex-Go=/func([ \t]+\([^)]+\))?[ \t]+([a-zA-Z0-9_]+)/\2/d,func/
--regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/d,var/
--regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/d,type/

と書き込んでおけば、関数定義元に(ある程度)ジャンプできるようなる。完璧にとはいかないが、今のところはこれでいいかと。

GOPATHとディレクトリ構造

ghqを使ったローカルリポジトリの統一的・効率的な管理について - delirious thoughts

基本は上記の記事の通り。GOPATH=$HOMEに設定してghqでGo以外のリポジトリも含めて~/src配下で一括管理する。

ただ、これだとctagsでタグを生成する際に全てのリポジトリを対象にしなくてはならず、タグ生成処理がものすごく重くなってしまい使いものにならなかった。やはり依存パッケージは個々のリポジトリ配下にほしい。

いろいろ試行錯誤した後、次のようにdirenvを使う方法に落ちついた。direnvはカレントディレクトリごとに環境変数を自動で切り替えてくれるツールで、以下の記事が参考になる。

direnvを使おう - Qiita

まず

brew install direnv

direnvをインストールし、zshの場合は~/.zshrcに以下を記述しておく。

export EDITOR=vim
eval "$(direnv hook zsh)"

さて、ホームのsrcディレクトリは以下のようになっている。

src
├── github.com
│   ├── laravel
│   │   ├── framework
│   │   └── laravel
│   ├── kohkimakimoto
│   │   └── altax
│   ├── php
│   │   └── php-src
│   └── piranha
│       └── gostatic

ここでGo言語の場合はリポジトリのルートに.envrcを作成して

export GOPATH=$(pwd)/_vendor/:$GOPATH

と書いておく。これでGo言語のリポジトリに移動した時のみGOPATHがそのリポジトリ配下の_vendorディレクトリにも設定される。go getで外部パッケージをインストールするとき_vendoer配下にインストールされるようになるし、go build時もここのパッケージを参照するようになる。ctagsのタグ生成もリポジトリルートで行えば依存のあるパッケージをだけを対象にタグを生成できる。

参考にしたサイトは以下。

ghqによるGoのプロジェクト管理 & プロジェクト毎で外部モジュール管理 - Qiita

これからGoを始める人のためのTips集 #golang - The Wacul Blog

Gomで依存パッケージを一括で_vendorにダウンロード

_vendorに依存パッケージを配置できるようになったのはいいのだが、依存物をいちいち手作業でgo getするのは非効率なので一括でダウンロードできるようにGo言語版のBundlerなやつであるGomを使っている。

mattn/gom · GitHub

以下のコマンドを叩くとgo buildを実行してインストールされていないパッケージをエラーメッセージから抽出してGomfileに吐き出す。

go build 2>&1 | awk '/cannot find package/{print "gom " $5}' >> Gomfile

これでGomfileができたら

gom install

として全ての依存パッケージを_vendor配下にダウンロードする。これでGoのプロジェクトがビルドできる\(^o^)/