BackEnd

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

投稿日:2018年10月9日 更新日:

はじめに

こんにちは、雨の日が最近多く、気温の変化が激しくて、体調管理に気をつけなければと思うこの頃です。

さて、今回はGo言語についてです。Go言語をご存知の方は、最近ですと、2018年8月末に1.11がリリースされことや、Go2でのgenericsやエラーハンドリングに関する議論など耳にされている方も多いのではないでしょうか。
改めて話題になってたことで、私たちもGo言語を改めて学びなおそうと、勉強会合宿を開催しました。そこで発表・共有した内容を簡単にまとめ、数回にわたり連載を予定しております。
今回の記事では、改めてGo言語を勉強してみたいという方向けに、Go言語概要と環境構築から、Go 1.11でexperimentalでリリースされた Modules について紹介したいと思います。

Go言語(Golang)とは

Go言語の連載最初の1回目の記事なので、簡単にGo言語についても説明します。
Go言語は、2009年にGoogleから発表されたオープンソース プログラミング言語です。当初は、Robert Griesemerと、UNIX開発に携わった著名な、Rob Pike、Ken Thompsonの3名によって開発が進められ、下記のような特徴を持っています。

シンプルな構文

Goは機能をシンプルに保つために、コア開発者全員が必要と思った機能だけを言語に取り込むという方針があるようです。例えば、三項演算子がなかったり、繰り返しをfor文だけに限定したりするなど、構文が最小限になっています。

また、if文の波括弧が省略不可など、開発者のよるコーディングのばらつきがなくなる工夫も言語機能として組み込まれています。
さらに、自動でコードをフォーマットする gofmtgoimports 、それからコードの静的解析をする go vetgolint など、コーディングに関して開発者をサポートするツール群が充実しています。(自動フォーマットツールは、フォーマットルールをカスタマイズする機能がなく、コーディングルールを言語として厳密に定めてる意図を感じます。)

コンパイル言語

Rubyなどのスクリプト言語とは異なり、コンパイルが必要な言語で、静的型付けの安全性があります。ただ、C++などの他のコンパイル言語と比べて、コンパイルがとても早く、スクリプト言語のような効率性もあります。また、様々なOS向けのクロスコンパイルをサポートしており、基本的にはコンパイルで生成された単一のバイナリファイルをデプロイすれば利用できます。

並行処理

スレッドモデルによる並行処理を、言語として標準で提供している goroutine / channel と言った機能を使うことで簡単に実装ができます。この goroutine などは改めてブログ記事にしたいと思います。

その他の特徴

割と新しい言語であるGo言語ですが、クラスというものがないということも特徴的だと思います。
オブジェクト指向的な表現をするためには、構造体(struct)を定義し、その構造体に対してメソッドを定義することで可能ですが、クラスの継承と言ったことはできません。これは、Go言語として、継承よりコンポジション(composition over inheritance)の設計思想があるようです。
その他、Goらしい書き方(Go Way)については、Effective Goという記事で色々と書かれています。ただ、まずは書いて見て、強力なツールである、 go vetgolint で警告を表示させ、理解しながら修正する方が学びが早いと思います。こういうところもGo言語の良さですね。

Go開発環境の構築

さて、Go言語の特徴の概要は、このくらいにして、次は開発環境の構築について、記載をしていきます。本記事の執筆時点で最新のGo 1.11を対象にしています。
Go言語はDockerを利用しての開発も多いと思いますが、インストールも簡単なので今回はローカルのMac PC上に構築する方法を紹介したいと思います。

Goのインストール

公式サイトからインストーラ(パッケージ)がダウンロードでき、それをインストールすればGo環境は完成です!
ただ、今回はMac PC上にインストールする際に、複数のGoバージョンを管理するための goenv というものを紹介します。 pyenv や rbenv とかと一緒の仕組みですので、詳細の説明は割愛して、インストール手順だけ記載します。

1. homebrewでgoenvをインストール

2. ~/.bash_profileに追記

3. Go 1.11.0をインストール

なお、上記では global でバージョンを1.11.0にしていますが、特定プロジェクト(ディレクトリ配下)だけで、バージョンを指定したい場合は、 local も利用できます。

本当に、 rbenv とかと全く一緒の使い勝手ですね。

環境変数

下記のコマンドを実行するとGo言語の開発に関連する環境変数の一覧が表示されます。今回はその中でも気にかけておくべき環境変数を2つ紹介します。

GOROOT

GOROOTは、Goがインストールされているディレクトリになります。
今回は、 goenv を使ってインストールしていますので、上記のようなパスになっています。 goenv でバージョンを切り替えると、GOROOTのパスも変更されます。基本的には個人で変更することはありませんが、Linux上でtarアーカイブなどでインストールした際には、展開先のディレクトリを指定することになるので知っておくと良いと思います。

GOPATH

GOPATHは、外部のパッケージなどのソースを取りまとめておくディレクトリを指定するものになります。
デフォルトでは、 $HOME/go となっています。また、外部パッケージ以外に自身のプロジェクト開発ディレクトリをGOPATH配下にされている方もいますが、今回はあとで紹介する Modules の利用もあり、開発ディレクトリは、GOPATHの外とし、かつ開発プロジェクト別にGOPATHを管理できるようにしたいと思います。そこで、 direnv というツールを紹介します。

direnv

direnv は、特にGo言語開発には関係のないツールですが、簡単に説明するとディレクトリ毎に環境変数を定義できるツールです。今回は各プロジェクト毎の開発ディレクトリのみで固有のGOPATHを設定してみたいと思います。 hello_go というプロジェクトを開発することを想定して、 hello_go というディレクトリ配下で開発をする場合を想定してみます。

direnv のインストールし、 .bash_profile に追記する

プロジェクト開発ディレクトリを作成し、環境変数を設定する

保存後に自動で読み込みが発生し、下記が出力されます。

これで、GOPATHの設定も完了です。実際は、gitでこのディレクトリを管理することになると思いますので、GOPATHのディレクトリは .gitignore に追加しておくことになると思います。

パッケージ バージョン管理

Go言語での開発はこれで始められますが、その前にもう一つパッケージの管理方法についても説明したいと思います。
Go言語は、インストールした時点の標準パッケージだけでも十分に開発が可能です。Webアプリケーションも標準パッケージだけで十分に開発できてしまいます。とはいえ、プロジェクトによっては、外部のオープンソースパッケージも利用したいことももちろんあると思います。そこで、外部のパッケージをインストールし、バージョンや依存などを管理するための機能が必要になります。

Go言語で外部パッケージを利用する際には、depといったような外部ツールを利用して、依存関係などパッケージを管理するがメジャーとなっています。
(標準の go get コマンドでgithubのリポジトリからコードを $GOPATH/src 配下にダウンロードして利用する方法もあります。)
depもまだまだ現役ではありますが、今回は、Goの標準として利用されるようになるだろう、 Modules を使ってみたいと思います。
少し雑な説明になりますが、Railsなどをご存知の方であれば、gemを想像していただければ良いかと思います。

Modulesとは

Modules は、「Goのパッケージには、バージョン付けが必要だ」ということで、Goのメインリポジトリの外で開発がスタートした vgo ツールが元になっています。(詳しくはこちらに和訳記事があります。)
vgo で一定の検証と評価がされ、2018年7月12日にGoのメインリポジトリに組み込まれました。そして、8月末にGo 1.11のexperimentalとしてリリースされました。また、1.12で正式リリース予定となっており、 dep から Modules への円滑な移行方法も検討されていることから、今後はこちらがデファクトになりそうです。

パッケージの追加

実際に Modules を利用して、外部パッケージを追加してみましょう。

1. Modulesの初期化

先ほど、作成した hello_go ディレクトリで実行します。重要なのは、環境変数の GOPATH で指定されたディレクトリ外で実行することです。

上記を実行すると go.mod というファイルが生成されます。このファイルにはインストールされた外部パッケージとそのバージョンが記載され、このファイルを配布することで他の開発者も同じバージョンのパッケージをインストールすることができます。(Gemfile.lockと同じような扱いですね。)

2. 外部パッケージの追加

Goのgithubのwikiにあるサンプルと同じですが、main.goというファイルを作成し、下記を実行しましょう。

main.goファイルで外部パッケージをimportさせて、buildを実行すると依存している外部パッケージがダウンロードされ、go.modへの追記とgo.sumファイルが生成されます。
go.modファイルには、必要とされる外部パッケージとバージョンが追記されているのがわかると思います。これで、go.modを配布するだけで各開発者の環境で同じパッケージが利用されるようになります。
では、go.sumファイルと何でしょうか。これは、ダウンロードされたパッケージのchecksumになります。後ほど、紹介するコマンドでダウンロードされたパッケージの検証をする際に利用されます。なお、パッケージは $GOPATH/pkg 配下にダウンロードされています。

その他のコマンド

go mod tidy

tidy は整頓という意味ですが、これを実行すると不要なパッケージを削除し、go.modにある必要なパッケージをインストールします。

go test ./…

go mod tidy を実行後に上記コマンドを実行するとダウンロードしたパッケージのテストコードを実行してくれます。

go verify

go.sumファイルを使い、ダウンロードされたパッケージが正しいものかを検証します。

go get -u

これは、go.modファイルにあるパッケージのアップグレードを行います。
go get -u は、パッケージを最新のマイナー及びパッチリリースへアップグレードをし、 go get -u=patch は、最新のパッチリリースへアップグレードを行います。

補足1:ビルドと実行

先ほど、main.goを実行するために、 go build でコンパイルし、生成したバイナリファイルを実行した例を紹介しました。実は、Go言語ではとりあえずの試し実行であれば、コンパイルでの実行バイナルファイルを生成しなくても動作を確認できるのです。
Go言語では、mainパッケージのmain関数がエントリーポイントとなりますので、そのファイルを直接指定すると実行を確認できます。

補足1:packageとimport

Go言語では、変数や関数など全てのプログラム要素は、何らかのパッケージに属することになります。今回の例ではプロジェクトのトップ階層に作成したmain.goの一行目に package main という記載があったと思いますが、これがそのパッケージになります。mainパッケージは特別な意味を持ちますが、プロジェクトが大きくなりディレクトリ階層などが作成された場合は、パッケージ名はディレクトリ名と同じにするのが通例のようです。
importは、ファイル内で使用するパッケージを指定するためのものです。importでパッケージを指定することでそのパッケージの公開関数や変数をそのファイル内で使用することができるようになります。今回の例では、標準パッケージのfmtと外部パッケージの rsc.io/quote を利用しました。

さいごに

いかがでしたでしょうか。Go言語のブログ連載の1回目は、まずは実行するための環境構築を説明させていただきました。私たちもGo言語を色々と勉強し、実際に使ってみることで、Goならではの面白さを感じることができました。ぜひ、皆さんもGo言語を学んでみてはいかがでしょうか。
2回目は、基本構文などの説明を予定していますので、ぜひご覧いただければと思います。

Go記事の連載などは、こちらをご覧ください。

おすすめ書籍

スターティングGo言語 (CodeZine BOOKS) Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ みんなのGo言語【現場で使える実践テクニック】 Go言語による並行処理

blog-page_footer_336




blog-page_footer_336




-BackEnd
-,

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

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

CAPTCHA


関連記事

FastAPIのPath Operationをasync defにするときはブロッキングに気をつけよう!

1 はじめに2 Path Operationと並行処理3 挙動の確認4 対応方法4.1 asyncioを使って自力で非同期化する4.2 async対応済みのパッケージを使う4.3 async defを ...

js

Moment Timezoneを使ってJavaScriptで日付を変換する

1 はじめに2 Moment Timezone2.1 セットアップ2.2 使用例3 Moment Timezoneの機能3.1 タイムゾーンの一覧を表示する3.2 現在のタイムゾーンを表示する3.3 ...

laravel logo

Laravelでテストコードを書くには? Featureテスト/Unitテスト

1 はじめに2 FeatureとUnitの使い分け3 テスト用データベースの準備4 Featureテスト4.1 テスト対象のコード4.2 テストコードの実装4.3 テスト結果の検証4.3.1 ステータ ...

docker-syncでファイルの同期を高速化する

1 はじめに2 docker-syncの導入3 設定ファイルの作成3.1 docker-composer.yml3.2 docker-compose-dev.yml3.3 docker-sync.ym ...

rails

Rails 6の変更点と新機能

1 はじめに2 概要3 Rubyのサポートバージョン4 Webpacker4.1 Webpackerの設定4.2 Webpackerでのビルド4.3 ビルドしたJavaScriptファイルを読み込む4 ...

フォロー

blog-page_side_responsive

2018年10月
 123456
78910111213
14151617181920
21222324252627
28293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。