はじめに
今まで以下の流れで開発環境を用意しました。
GoModulesの存在を知り、以下の理由からもう一度開発環境を見直すことにしました。
- バージョン管理のデファクトスタンダードになる(なってる?)GoModulesを理解したかった
- GoModulesを使用することで、設定に苦しんだGOPATH関連の制限から解放されそうだった
Go Modules
GoModulesは、Go1.11から導入され始めたGoの新しいバージョン管理システムになります。
詳細については、以下を参照いただくのが良いと思います。
GoModulesの概要から、今までのバージョン管理との違いまで把握できます。
GOPATH mode から module-aware mode
今まで(GOPATH mode)は標準pkg以外を全部 $GOPATH
以下のディレクトリで管理する仕様となっており
プロジェクトも $GOPATH/src
配下に作成する必要がありました。この制約で上記の開発環境を用意する際にかなり苦しみました。
しかし、module-aware mode では標準pkg以外の全てのパッケージをモジュールとして扱い、モジュールの管理やビルドが任意のディレクトリで可能になりました。($GOPATH/src にプロジェクトを配置しちゃダメというわけではなそう)
環境構築
go(1.10以降)とVSCodeはインストール済みの状態から始めたいと思います
私はgo(1.13.1)、VSCode(1.38.1)でやっています
環境変数
export PATH=$GOPATH/bin:$PATH
export GOPATH=$HOME/go
export GO111MODULE=on
※GOPATHはプロジェクトと違うディレクトリで試したかったので $HOME/go
にしています
GO111MODULE
はGOPATH modeとmodule-aware modeを切り替えるための環境変数です。
Go 1.13からデフォルトが on
になる予定だったようですが、どうやら auto
がデフォルトになっているそうです。
そのため環境変数に上記を設定します。
-
on
:Go modules を使う (module-aware mode) -
off
:$GOPATH を使う (GOPATH mode) -
auto
:$GOPATH/src の外に対象のリポジトリがあり、 go.mod が存在する場合は module-aware mode、そうでない場合は GOPATH mode
ディレクトリの作成
以下の構成でディレクトリを作成します
$ tree -F GolangProjects
GolangProjects
└── github.com/
└── so-heee/
└── modules_example/
モジュールの初期化
以下のコマンドでモジュールを初期化します
初期化すると go.mod
ファイル(モジュールを管理するファイル)が出来ます
$ go mod init github.com/so-hee/modules_example
go: creating new go.mod: module github.com/so-hee/modules_example
└── modules_example
└── go.mod
サンプルプログラムの作成
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
ビルドと実行
作成したファイルをビルドすると、依存パッケージである rsc.io/quote
がダウンロードされます
$ go build -o hello
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
GOPATHに設定したディレクトリにパッケージがダウンロードされています
$ tree -F go -L 3 -d
go
└── pkg
└── mod
├── cache
├── golang.org
└── rsc.io
また go.sum
ファイル(依存モジュールのチェックサムの管理をしてるファイル)が作成されています
ビルドしたファイルを実行してみます
$ ./hello
Hello, world.
VSCodeでの環境設定
上記のフォルダをVSCodeで開きます
拡張機能インストール
Cmd + Shif + x でExtensionMarketplaceを開いてGoをインストール
先ほど作成したhello.goのファイルを開くとツールのパッケージをインストールするか聞かれるのでインストールしましょう
聞かれない場合がもしあった場合は、Cmd + Shift + P でコマンドパレットを表示
GO: Install/Update Tools
で全て選択してインストールしましょう
独自パッケージの作成
新規でパッケージを作成し、mainでimportしてみます
package calc
// Sum は引数a, bを合算して返却します
func Sum(a, b int) int {
return a + b
}
package main
import (
"fmt"
"github.com/so-heee/modules_example/calc"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
fmt.Println(calc.Sum(1, 2))
}
問題なくimportできたので、実行してみます。F5でデバッグしてみます
Hello, world.
3
Dockerを使った開発環境の設定
dockerのインストール
Homebrewでdockerをインストールします(Homebrewの使い方は省略します)
$ brew cask install docker
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
dbmate kops mosquitto rabbitmq
==> Satisfying dependencies
==> Downloading https://download.docker.com/mac/stable/38240/Docker.dmg
######################################################################## 100.0%
==> Verifying SHA-256 checksum for Cask 'docker'.
==> Installing Cask docker
==> Moving App 'Docker.app' to '/Applications/Docker.app'.
🍺 docker was successfully installed!
$ docker --version
Docker version 19.03.2, build 6a30dfc
VSCodeにRemote-Containersのインストール
Cmd + Shif + x でExtensionMarketplaceを開いて Remote-Containers
を検索してインストールします
設定ファイルの作成
左下の矢印アイコンを選択します
今度は Remote-Containers: Add Development Container Configuration Files
を選択します
何の開発環境を作るか聞かれるためGo
を選択します
選択すると先ほどのサンプルであった.devcontainer
ディレクトリが作成され
その下にdevcontainer.json
とDockerfile
が入っています
Dockerコンテナの作成
左下の矢印アイコンを選択します
Remote-Containers: Open Folder in Container
を選択し、フォルダを選択します
ビルドが開始されます
ビルド中にdetailsを押すと、ターミナルにビルドの状況が表示されます
完了するとエクスプローラーに表示されます
コンテナ上でGOのプログラムを実行
ターミナルタブを開いて、右側のプルダウンを 1:bash
にします
hello.goを実行してみます
するとコンテナ上のGOPATH(devcontainer.jsonのgo:gopath)に依存パッケージがダウンロードされます
ローカルの時と同じですね。
root@4f93101644d1:/workspaces/GolangProjects/github.com/so-heee/modules_example# go run ./hello.go
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: finding rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
こんにちは世界。
3
※こんにちは世界になるのは別の問題だと思うので今回は無視します(F5実行は問題ありません)
課題(依存先モジュールの編集する時)
githubで公開すると、基本的にそちらを参照してしまうため、ローカルで修正しても動作が変わりませんでした。。。
対応策としてgo.modを一時的に書き換えてreplaceディレクティブを使う方法や、go mod vendor でvendorを書き出してしまってそれを編集するなどがあるようですが、そもそも開発スタイルが正しいのか不安が残ります。
こちら解決策ご存知の方、もしくは別の方法をとってる方などいましたら是非ご教示ください!!
参考:最近のGo Modulesプラクティス ~ ghqユーザーの場合も添えて