読者です 読者をやめる 読者になる 読者になる

初老のボケ防止日記

おっさんのひとりごとだから気にしないようにな。

スポンサーリンク

はじめてのGo(2)



前回はGo言語の開発環境の導入をしたのだが、

ハロワだけできても意味ないんですよ。

ということで、実際の開発に即した感じの手順を模索してみるシリーズ(あくまで模索なのでコレがGo言語的に正しいのかは不明)。

今回は分割コンパイルについて。

分割コンパイルとは

実際のソフトウェア開発において、プログラムを記述するソースコード(今回でいう○○.goファイル)がひとつだけっていうことはまずない。

だって、そんな単純じゃないもの。
普通は機能ごととかの単位でソースコードァイルを分けて記述して、それぞれをコンパイルして生成されたオブジェクトをリンカで結合して実行ファイルを作成します。

ってそれはC言語の話。

でも、Go言語も恐らく同じ感じだと思うので分割コンパイルの方法を試してみる。

環境

OS Windwos 10 Pro
Go 1.6.2
IntelliJ IDEA 2016.1.3
Goプラグイン 0.11.1295

なお、コマンドラインはGitBashである。

ビルドツール

IDEAのGoプラグインで分割コンパイルを色々とやってみたんだけれども、結論から言うと

しんどい。

できなくもないのだが、外部ライブラリの管理とか考えるとIDEAはあくまでエディターとして頑張ってもらうことにしてビルドについてはビルドツールに頼るのが楽かなと思った。

で、ビルドツールも色々とあるんだけど今回は 「ジャスト一分だ。良い夢見れたかよ?」でお馴染みのGBさんに。

getgb.io

GBさんの特徴は

A project based build tool for the Go programming language.

プロジェクトベースのビルドツールだという点。
Go言語もナウでヤングな言語なのでJavaやPythonやRubyと同様に、豊富な標準パッケージ以外にOSSな外部パッケージが沢山公開されている。で、Go言語の場合はGOPATHという環境変数で指定した場所に外部パッケージがインストールされるらしい。

GOPATH環境変数はワークスペースの場所を示してします。これがGoコードを開発する際に設定が必要な唯一の環境変数のはずです。

始めるにあたっては、ワークスペースディレクトリを作成し、適宜GOPATHをセットしてください。ワークスペースはどこでも好きな場所に置いてよいですが、このドキュメントでは$HOME/goとして説明しています。Goをインストールしたパスを指定してはいけないことを注意してください。

Goコードの書き方 - The Go Programming Language

GOPATH自体は環境変数なので切り替えもできるのだが、仮に自分の開発環境でひとつの場所とした場合に、全てのプロジェクトで同一のモノを見てしまうので便利なこともあればちょっと不味い場合もある。前者であれば便利コマンド的なもの(GB自体がgbコマンドとしてインストールされる)。後者であれば、例えば色々なプロジェクトで利用されるパッケージなのだが、開発スピードが早いので同じモノを参照すると使用時期によってAPI仕様や挙動が変わってしまうのでまいっちんぐとか。で、それを避けるにはプロジェクト単位で依存関係を管理した方がよくない?というのがGBさんのアプローチな模様。

インストール

ということで、早速GBをインストールしてみましょう。

gb · Installation

で、先程書いたとおり、GB自体も外部パッケージなのでGOPATHを定義しないとインストールできません…。

$ echo $GOPATH
C:\Users\osa\.go

ということで、プロジェクトに依存しないグローバルなGOPATHを指定します。

$ go get github.com/constabulary/gb/...
$ ls $GOPATH/bin
gb.exe  gb-vendor.exe

GOPATHが指定されていれば「go get」でインストール完了。「GOPATH/bin」にパスを通しておくと便利です。

試してみる

公式の以下の説明に従って試してみる。

gb · Projects

$ mkdir -p gokumi/src/hello
$ tree gokumi -F
gokumi
`-- src/
    `-- hello/

プロジェクトのディレクトリはGOPATH配下でなくても問題なし。ただし、プロジェクトディレクトリ配下に「src」が必要なのだ。

$ cat <<EOF > gokumi/src/hello/hello.go
package main

import "fmt"

func main() {
    fmt.Println("Hello gb")
}
EOF
$ tree gokumi -F
gokumi
`-- src/
    `-- hello/
        `-- hello.go

「プロジェクトディレクトリ/src」配下にパッケージ単位でディレクトリを作成してソースファイルを配置する。ディレクトリ名とパッケージ名が必ずしも一致していない点に注意。

$ cd gokumi/
$ gb build all
hello
$ bin/hello.exe
Hello gb

プロジェクトディレクトリに移動してビルド実行。「プロジェクトディレクトリ/bin」配下に実行ファイルが生成される。

プロジェクトで複数の実行ファイルを生成してみる。

実際の開発だと、一つのプロジェクトから複数の実行ファイルを生成することもよくある。Server/Clientとか。今度は複数実行ファイルを生成するパターンをGBとIDEAでやってみる(IDEAはコードを書くだけ)。

構成

プロジェクトのディレクトリ構成はこんな感じ。

$ cd gogoheaven
$ tree . -F -I *.iml
.
`-- src/
    |-- cmd/
    |   |-- eriko/
    |   |   `-- main.go
    |   |-- hiroko/
    |   |   `-- main.go
    |   |-- hitoe/
    |   |   `-- main.go
    |   `-- takako/
    |       `-- main.go
    `-- common/
        `-- speed/
            `-- member.go

IDEAのプロジェクトも「gogoheaven」がプロジェクトディレクトリになっている。

コード補完用のIDEA設定

GBはビルド時にカレントディレクトリをGOPATHに指定することで依存関係を解決しているっぽいのだが、IDEAのGOプラグインはそんなことを知らない。なのでそのままだとコード補完が効かない残念な子になってしまう。

f:id:osa030:20160707224140p:plain

こんな感じで「知らない子」扱い。

f:id:osa030:20160707224215p:plain

「File」->「Settings」で設定画面を開いて、「Languages & Frameworks」->「Go Libraries」をクリック。
「Project Libraries」の「+(Add)」をクリック。

f:id:osa030:20160707224223p:plain

現在のプロジェクトディレクトリを指定して「Apply」して「Ok」で画面を閉じる。

f:id:osa030:20160707224230p:plain

ほうら、もう君もトモダチさ。

コード

補完が効くようになったら各ソースファイルはこんな感じでガシガシ作る。

  • common/speed/member.go
package speed

import "fmt"

type Member struct {
	Name string
}

func (m Member)Say()  {
	fmt.Printf("SPEEDの%sです。•̀.̫•́✧\n", m.Name)
}
  • cmd/eriko/main.go
package main

import "common/speed"

func main() {
	member := speed.Member{ Name:"elly" }
	member.Say()
}
  • cmd/hiroko/main.go
package main

import "common/speed"

func main() {
	member := speed.Member{ Name:"hiro" }
	member.Say()
}
  • cmd/hitoe/main.go
package main

import "common/speed"

func main() {
	member := speed.Member{ Name:"HITOE" }
	member.Say()
}
  • cmd/takako/main.go
package main

import "common/speed"

func main() {
	member := speed.Member{ Name:"たかこ" }
	member.Say()

}

ビルド

コマンドラインからGBでビルド。main関数が定義されているものは全部ビルドしてくれるようだ。

$ gb build all
common/speed
cmd/hitoe
cmd/takako
cmd/eriko
cmd/hiroko

$ ls bin
eriko.exe  hiroko.exe  hitoe.exe  takako.exe

実行

ということで、実行。

$ bin/hitoe.exe
SPEEDのHITOEです。•̀.̫•́✧

$ bin/takako.exe
SPEEDのたかこです。•̀.̫•́✧

$ bin/eriko.exe
SPEEDのellyです。•̀.̫•́✧

$ bin/hiroko.exe
SPEEDのhiroです。•̀.̫•́✧

GB、恐ろしい子。

スターティングGo言語 (CodeZine BOOKS)

スターティングGo言語 (CodeZine BOOKS)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

SPEED スピード コンプリートベスト AQCD-50568

SPEED スピード コンプリートベスト AQCD-50568

スポンサーリンク