【macユーザ向け】 goenvの導入方法とModuleの使い方

皆様はじめまして、社会人2年エンジニアのymitomoと申します!

本記事ではタイトルにある通り、goenvの導入と最近導入されたModuleの使い方について説明していきます。

先日Goバージョン1.12系が正式にリリースされました。
https://golang.org/doc/go1.12 f:id:ymitomo:20190623225226p:plain

1.12へのアップデートで大きく変わったことと言えば、1.11から存在するModuleがより強くサポートされたことです。次回のメジャーアップデートの対象となる1.13系から正式に、依存関係の管理がModuleに完全移行するようなのでdepを使用している方は今のうちからModuleに慣れておいた方が良いでしょう。

ということで、go未導入の方はもちろん、1.12以前のバージョンを使用しているユーザにも向けdepでの依存関係からModuleでの依存関係の管理に移行をする方法を簡単にご紹介していきます。

1.12の導入

一般的にgoのインストール方法は2種類あります。

1. HomeBrewを使用してinstall  
2. goenvを使用してのinstall  

goenvというのは、goのバージョンを細かく手軽に指定できるバージョン管理ツールのことです。
Homebrewでのgoのinstallよりも、こちらの方が後々使い勝手が良いので今回はgoenvを使用して1.12系を導入します。
私は仕事で使用するコンポーネントが狭い範囲のマイナーバージョンしか対応していなかったということがあったので、goenvを使用しています。

ただ、goenvを使わずとも $ brew update go でgoのバージョンをlatestまであげることができます。 これだけでもgo Moduleを使用することができるので、これでも良いという方はgoenv、goの導入をスキップして読み進めてください。

goenv導入

https://github.com/syndbg/goenv

HomeBrewでgoenvをinstallすることができますが、homebrewで取得されるgoenvでは、go1.12系が1.12betaというバージョンしかないのであまりオススメできません。

goenvのレポジトリをcloneしてくる

$ git clone https://github.com/syndbg/goenv.git ~/.goenv

goenv用の環境変数を設定
~/.bash_rc~/.bash_profileを作成してそこに書いていくのが良いでしょう。

export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"

設定したファイルを読み込んで準備完了となります。

$ source ~/.bash_profile

実際に環境変数にセットされたか確認してみましょう。

$ env | grep goenv

GOENV_ROOT=/Users/<user_name>/.goenv
PATH=/User/<user_name/>....

goの導入

ここまででgoenvの導入は完了したので続いて、goのバージョンを指定してgoのinstallを行いましょう。
今回はバージョン1.12.1を指定します。といっても、他のバージョンでもやることに変わりはありませんので適宜1.12.1を自分が入れたいバージョンに置き換えてください。

使用可能なバージョンを確認する

$ goenv install -l

  .
  .
  .
  1.12.0
  1.12beta1
  1.12beta2
  1.12rc1
  1.12.1 ← コレ
  1.12.2
  1.12.3
  1.12.4
  1.12.5

1.12.1が利用可能なバージョンであることが確認できました。1.12.1のインストールを行います。

$ goenv install 1.12.1
$ goenv global 1.12.1

installが完了しました!簡単ですね! versionが自分のinstallしたバージョンになっていれば問題ありません。

$ go version

go version go1.12.1 darwin/amd64

バージョンの切り替え、アンインストールについては下記コマンドで行うことができます。

// uninstall
$ goenv uninstall <version>
// バージョン切り替え
$ goenv glbal <version>

buildができない?

ここまででgoのinstallは完了です。しかし、現状のままだとbuildを動かすことができません。下記のようなエラーがでます。

can't load package: package .: no Go files in /Users/<user_name>/go/src/..... 

これはGOPATHが違うと言われていますね。なんで?と思う方、ここにちょっとした落とし穴がありますので注意が必要です。

go関連の環境変数を確認する際には、go envコマンドを使用するようにしてください。実際にGOPATHを書いたbashファイルの中身やenvコマンドの出力だろうと、go envで確認できるものが正となります。
ということでgo env | grep GOPTAHコマンドを実行。

GOPATH="/User/<user_name>/go/1.12.1"

なぜか勝手にgopathが変わってしまっているのがわかります。
試しにGOPATH配下に1.12.1というディレクトリを作成して、普段から使用しているプロジェクト(GOPATH配下)を1.12.1ディレクトリ配下にコピーし、buildをしてみると問題なく実行することが確認できます。

<GOPATH>/1.12.1/project

ということで、go envで確認したGOPATHに合わせるようにディレクトリ構成を変更してみてください。

ディレクトリ構造変更の回避方法

上記でgoenvでgoのインストールを行うと、ディレクトリ構造を対象バージョンごとに変更する必要があると説明させていただきましたが、今まで通りのGOPATHをそのまま使用し続けることも可能です。

そもそもGOPATHが変わってしまうのは、goenvのGOPATH管理設定が効いてしまっているからです。 ということは、設定を消してあげればいいんです!!ということで下記の設定を環境変数として読み込ませてみましょう。

export GOENV_DISABLE_GOPATH=1

すると、goenvでのGOPATH管理設定が無効になり、GOPATHが元に戻っているのが確認できるかと思います。

GOPATH="/User/<user_name>/go"

Moduleについて

ここまで長くなりましたが、Moduleの説明をざっくりとします。
Moduleはgo1.11から試験的に導入さた、depに変わり依存関係を管理してくれるやつと思っていただいて大丈夫です。

現在は試験的に適用されていますが、次の1.13系へのメジャーアップデートの際に正式にサポートされるようです。

実際の使い方

使い方はとても簡単で、下記コマンドを実行するだけです。こちらも環境変数bashファイル等に記述しておくと良いでしょう。

環境変数を設定(1.13以降ではdefaultでonになるとのこと)
$ export GO111MODULE=on

$ go mod init

これでgo.modとgo.sumという二つのファイルが作成されます。

以降buildやginkgoなどのテストを行うたびに、依存関係が勝手に読み込まれgo.modに登録されていきます。dep ensureのように手間がかからないのでとても便利です。

depからmodに移行ができない?

最近go言語を始めたよーという方でなければ、多くの方々が今までdepで依存関係の管理をしてきたのではないでしょうか?vender, Gopk.lockなどですね。
実際に私はdep ensureを叩いて管理をしていました。

ですが、dep ensureコマンドさえもあまり理解せず実行していたため、go.modファイルで定義されているpackage等のバージョンが古かったり、module対応していなかったりで、1.12系にバージョンアップした直後はbuildもできない状態になってしまいました。

このbuildができない原因としては、gopkg.lock、venderなどのdepの遺産がが残っていたことにあります。
go mod initで初期化してもgopkg.lockが残っていると、gopkg.lockを参照してgo.modが作成されます。そのため古い依存関係がmodファイルに書き込まれてしまうために、一部のpackageのバージョンがmoduleに対応していなかったりということが発生したためエラーが発生してしまっていたようです。

ではこの問題をどのように解消すれば良いか。簡単です。dep initdep ensureで生成されたファイルを全て削除してしまえば良いのです。
ファイルが全て削除された状態で、再度go mod initを実施すると依存関係が何も書かれていない初期化されたgo.modが生成されます。
この状態でbuildを行うと、ファイルに定義されている依存関係(外部package等)が自動的にgo.modに依存関係として保存されます。

これにて設定は完了です。以降はbuildするだけで依存関係を更新してくれるので依存関係更新のためのコマンド等は特に必要ありません。

dep ensureは使わない方が良い

使わない方が良いという理由は単純です。1.13からmoduleに完全移行するとのことなので今のうちからmoduleにしておいた方が、1.13系になった時にも設定に困らずに済むからです。

ただ、depで生成されるファイル構成でしか動作しない環境等あるとおもいますので、その際には適宜入れ替えが必要でしょう。

まとめ

いかがでしたでしょうか?今回はgoenvの使用方法とmoduleの簡単な使用方法を書きました。
私自身まだ、moduleや1.12のバージョンは勉強途中なので「そこ間違っている」や「そこもっと良い方法がある」等あればぜひコメントいただければと思います。

最後まで読んでくださりありがとうございました。