Go Modulesも触れてみるGo入門

Pocket

Go Modulesも触れてみるGo入門

「Go言語ってどう?」と聞かれたり、Goで実装されたツールをカスタマイズする機会があったりしたのでGoに入門しました。

Goのプロジェクトで見かける GOPATH, vendor, Go Modules(vgo)について分かりづらかった🤔ので明らかにしながら、簡単なプロジェクトの始め方から入ろうと思います!

Goとは

2009年11月にGoogleから発表されたプログラミング言語で、ソースコードをコンパイルして実行するコンパイル型言語です。
シンプルさが求められて比較的簡単に学習できる言語です。

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.
https://golang.org/

有名な例だと、コンテナ型仮想環境を実現するDocker 本体が Goで実装されています🐳

また、パッケージというシステムがあり公式で用意されているパッケージでWebサーバを立てられるほか、GitHubなどからの外部パッケージを取得して便利な機能を使うことができます。

詳しくは他の記事に譲るとして、新しいGo Modulesでパッケージ取得を体験しながら入門しましょう。

Go Modulesとは

Go 1.11 から追加された外部パッケージの管理システムです。vgoと呼ばれることもあります。
プロジェクトを作るなどの作業を(後ほど説明する) GOPATH の下でしなければならない制限が解消されます。

https://golang.org/doc/go1.11#modules

インストール

UNIXのターミナルが使えるときは anyenvgoenv を導入しておきましょう。 RubyとかPythonとか他の言語も触るとき便利ですよ😃
anyenvを導入した場合は、次のように Go のインストールができます。

anyenv install goenv
exec $SHELL -l
goenv install -l
goenv install 1.12.5
goenv global 1.12.5
goenv rehash

GOPATH は?

環境構築するときに GOPATH を設定することがあります。 GOPATH はデフォルトで ~/go/<バージョン> になっていて、 Go Modulesを使う範囲では手で作らなくとも自動的に作成されます。

そして、このあとのGo Modulesで外部パッケージを取得するときに保存される場所でもあり、 ~/go/<バージョン>/pkg/mod に保存されます。

また、 go install で実行ファイルを配置する先が GOPATH/bin になるため、PATHを通すことをおすすめします。

PATH=$PATH:$GOPATH/bin

(Go Modulesとは別のツールで)必要なパッケージを用意してくれる dep を使う場合、取得したファイルは GOPATH/pkg/dep の下に配置されます。
ちなみに depを使うプロジェクトが GOPATH/src の下にいないと次のエラーでパッケージを取得することができなくなります。

/path/to/go-project is not within a known GOPATH/src

vendor を使っているプロジェクトもあるよ?

GitHub等でGoを用いたプロジェクトを見ると、 vendor ディレクトリを使っているところがあります(ビルド方法や Makefiledep ensure を用いているものがそうです)

  • Go のプロジェクトに vendor があると、ビルド時 自動的にそれを使います
  • また、先程の dep では dep ensure を実行すると指定されたバージョンのパッケージを vendor に配置しています

#初見でGitHubにあるGoのプロジェクトを改造したときに vendor の挙動がわからなくてハマりました。

ただし、Go Modlues(vgo)が出た当初は GOPATH/srcvendor を廃止するようで、Go Modulesを使っているときはデフォルトで vendor は無視されます。
要望もあるため 2019/06/13 現在も vendor が使えるようになっています。Go Modulesの設定によって vendor を使うようにすることもできます。

The initial series of vgo blog posts did propose dropping vendoring entirely, but feedback from the community resulted in retaining support for vendoring.
By default, go commands like go build ignore the vendor directory when in module mode.

https://github.com/golang/go/wiki/Modules#how-do-i-use-vendoring-with-modules-is-vendoring-going-away

vgo v.s. dep

ちなみに、Goの外部パッケージ管理としてどのくらい使われているのか、どれくらい調べられているのか(Google トレンド での情報ですが)を見ると、まだまだ dep のほうが強い印象があります。

Google Trends with go

Google Trends with golang

Modulesを使う場合

はじめに、Goのプロジェクトとなるディレクトリを作成して、 go mod init を実行します。
GOPATH/src 以下にディレクトリを作った状態で go mod init を実行するとModulesが無効化されている旨のメッセージが出るため、 GOPATH 以外の場所にディレクトリを作りましょう。

go: modules disabled inside GOPATH/src by GO111MODULE=auto; see ‘go help modules’

mkdir go-project
go mod init go-project

go mod init のあとにプロジェクト名を指定しないと次のエラーが出ます。

go: cannot determine module path for source directory /path/to/go-project (outside GOPATH, no import comments)

実行したあとは go.mod のファイルが作成されています。

$ ls
go.mod

次に、 main.go のファイルを作り、外部パッケージを体験するために次のコードを使います。
https://github.com/hackebrot/turtle の README.md とほぼ同じです。

vi main.go
package main

import (
	"fmt"
	"os"

	"github.com/hackebrot/turtle"
)

func main() {
	name := "wolf"
	emoji, ok := turtle.Emojis[name]

	if !ok {
		fmt.Fprintf(os.Stderr, "no emoji found for name: %v\n", name)
		os.Exit(1)
	}

	fmt.Printf("Name: %q\n", emoji.Name)
	fmt.Printf("Char: %s\n", emoji.Char)
	fmt.Printf("Category: %q\n", emoji.Category)
	fmt.Printf("Keywords: %q\n", emoji.Keywords)
}

最後に、ソースコードをビルドして実行しましょう。
出来上がった実行ファイルは go mod init で指定したプロジェクト名になります
(example.com/sample のように作った場合は実行ファイルの名前が sample になります)

go build
./go-project

たったこれだけです😁内容は実行してのお楽しみに

これまでのように dep を導入して GOPATH を設定して…をせずともModulesを有効にした状態で go build をすると外部パッケージを自動で取得してビルドまで進めてくれます。

Modulesを使った場合の外部パッケージのバージョン管理

ちなみにパッケージのバージョンは go.mod で管理されています 😁

$ cat go.mod
module go-project

go 1.12

require (
	github.com/google/go-cmp v0.3.0 // indirect
	github.com/hackebrot/go-repr v0.0.0-20170331152400-586d894a5734 // indirect
	github.com/hackebrot/turtle v0.1.0
)

Modulesを使わず go get する場合

Go Modulesを使わない場合も見てみましょう。
まず、プロジェクトを作成するのですが、GOPATH/src 以下のディレクトリはGo Modulesが無効化されることを利用して GOPATH/src/ にプロジェクトを作りましょう。

$ pwd
/path/to/gopath/
$ mkdir -p src/example.com/go-project
$ cd src/example.com/go-project
$ pwd
/path/to/gopath/src/example.com/go-project

続いて、 go get で必要なパッケージを取得します。

go get "github.com/hackebrot/turtle"

「Modulesを使う場合」と同様に main.go を作って、実行しましょう。 ソースコードの内容は同じです。

vi main.go
go build
./go-project

go get で外部パッケージを取得した場合

さて、Modulesを使った場合と、go get を使った場合は何が違うのでしょうか。
Modulesの場合、 go get を使わずにパッケージを取得できる利点は説明しました。

さらに、ビルド後のプロジェクト内や go get で取得したパッケージの場所をみると、パッケージのバージョンを表すものが何もありません。

$ ls
main.go	sample
$ ls $GOPATH/src/github.com/hackebrot/turtle
CONTRIBUTORS.md		README.md		doc.go			examples_test.go	filters_test.go		turtle_test.go
LICENSE			cmd			emojis.go		filters.go		turtle.go

このように、 go get で外部パッケージを取得すると パッケージのバージョンが管理されず、最新の状態でパッケージがダウンロードされます。
プロジェクトごとに外部パッケージのバージョンを決めたいときや、複数人でプロジェクトを共有してバージョンを揃えたいときに不便になります。

Go Modulesが登場する前は dep などでパッケージのバージョン管理をしていました。これからは公式で、Goを導入した瞬間にこのパッケージのバージョン管理ができるのです。

次のステップとしては

簡単ではありますが、Go Modulesの使い方を把握してGoプロジェクトの始め方をつかめたはずです。次の記事を参考にしてGoでできることを増やしましょう。

A Tour of Go(日本語版)

文法を覚えるには A Tour of Go で 実際に入力しながら 進めるのをおすすめします。ディレクトリを用意せずともGoの文法に触れられます。
流し読みしたらfor文を書くところで一瞬「あれ?」となりました

ただし「ニュートン法による平方根の求め方」などとっつきにくい部分があります。
#ニュートン法のところで何をしていいか分からなければ、とりあえず10回ループさせて2の平方根を求めてみてください😀

A Tour of Go(日本語版)
https://go-tour-jp.appspot.com/welcome/1

Go言語の初心者が見ると幸せになれる場所 #golang

そのほかに、Goを始めるときや、より良いコードを書くために必要なことがまとまっている次の記事が参考になります。

Go言語の初心者が見ると幸せになれる場所 #golang
https://qiita.com/tenntenn/items/0e33a4959250d1a55045

Go言語の基礎〜Go 1.11 開発環境構築とパッケージバージョン管理〜

また、 この記事ではGo Modulesについてさわりしかやっていないので、もう少しModulesのコマンドに触れてみたいと感じたならこちらも参考になります。

Go言語の基礎〜Go 1.11 開発環境構築とパッケージバージョン管理〜

Go言語の基礎〜Go 1.11 開発環境構築とパッケージバージョン管理〜

Awesome Go : 素晴らしい Go のフレームワーク・ライブラリ・ソフトウェアの数々

サンプルを作るにあたり、Goの外部パッケージを探すにはこちらが参考になりました。

Awesome Go : 素晴らしい Go のフレームワーク・ライブラリ・ソフトウェアの数々
https://qiita.com/hatai/items/f31914f37dc6c53b2bce

あとがき

Go Modulesの場合は GOPATH を設定しなくても動作します。

しかし、現在でもパッケージ管理にGo Modulesではなくdepが使われているように見え、depを使う場合は GOPATH を用意しないと正しく動作しません。
また、GOPATHについて調べていくと、Goでプロジェクトを作って開発し始めるには github.com/user/repository のような形でGOPATHに…という情報もあり、混乱しがちでした 😵

本記事のようにGitHubのリポジトリを意識しない形式でもプロジェクトは始められますが、GitHubを意識したプロジェクト構成で、名前は go-sample でもいいので学習結果をGitHubに残したほうが良いかもしれませんね😉

The Go Gopher by Renee French CC BY 3.0

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です