Go言語でサクッとコマンドラインツールをつくる

こんにちは!エウレカの田野です。

 

2016年もはじまり、今年は新しい言語を習得しよう!と1年の抱負を持ったかたもいらっしゃると思います。Go言語は(1)言語仕様が簡単で書きやすい、(2)クロスコンパイルができる、(3)高速に動作する、ので習得がオススメです! 

「ワタシハ ゴーゲンゴ チョットデキル」と言ってみませんか。(出典元: LinuxCon Tシャツ … 会社で作ってくれないかな。)
 

「Go言語で何か動くモノを作ってみたい!」という方のために、コマンドラインツールをサクッと作れるようサンプルアプリを作ってみました。

https://gist.github.com/MakoTano/624fe3fdea914b262e2c

本稿では、このサンプルアプリを解説していきます。

 

※なおこの記事は先日開催されたオープンソースライブラリ研究会 #3発表しましたLTの内容を、ブログへおろしたものです。

発表資料

サンプルアプリの開発方針

サンプルアプリを作るにあたって方針として考えたのは、以下のような条件を満たすものです。

  • 1つのプロジェクトで、複数個のサブコマンドを実装できる。
  • 引数やコマンドオプションの設定が整理された形で書け、視認性がよく改変しやすい。
  • コマンドヘルプの自動生成機能がある。

Go言語標準パッケージのos.Argsで引数、flagでコマンドオプションを伴ったコマンドが書けますが、上記の要件を満たすためには、書かなければならないコードの量が多くなりがちです。<そこで、コマンドラインツールの開発に必要な機能がまとまっているパッケージcodegangsta/cliを今回は利用します。

コマンドラインツールのサンプルアプリ

サンプルアプリをコピーして実行してみましょう。

$ mkdir -p $GOPATH/src/sample | cd $_
# ライブラリをインストールします。
$ go get github.com/codegangsta/cli
# サンプルアプリの内容をコピーします。
$ vi main.go
# main というバイナリができあがります。
$ go build main.go
コマンドヘルプ
コマンドを無指定で実行すると、HELPを表示します。
$ ./main
開始
NAME:
sample_client - github.com/codegangsta/cli のサンプルアプリです
USAGE:
main [global options] command [command options] [arguments...]
VERSION:
0.0.1
COMMANDS:
hello, h hello world を表示します
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--dryrun, -d
--help, -h show help
--version, -v print the version
終了
コマンド実行
helloコマンドを動かしてみましょう。
$ ./main hello 
開始
Hello world!
終了
# 引数を渡す
$ ./main hello Tom
開始
Hello world! Tom
終了
# グローバルオプションを渡す
$ ./main --dryrun hello Tom
開始
this is dry-run
Hello world! Tom
終了
コンパイルせずにコマンド実行する
上記の例はコンパイルしたバイナリを実行していますが、go runコマンドを利用することで、ビルドと実行を同時に行えます。開発時は主にこちらを使います。

上記例と同じように実行してみましょう。
$ go run main.go hello 
開始
Hello world!
終了
# 引数を渡す
$ go run main.go hello Tom
開始
Hello world! Tom
終了
# グローバルオプションを渡す
$ go run main.go --dryrun hello Tom
開始
this is dry-run
Hello world! Tom
終了
サンプルアプリの説明
ここからはサンプルアプリの中身を説明していきます。

https://gist.github.com/MakoTano/624fe3fdea914b262e2c
コマンドの設定
コマンドの設定は、サンプルアプリ内のこちらのコードで実装しています。
app.Commands = []cli.Command{
// コマンド設定
{
Name: "hello",
Aliases: []string{"h"},
Usage: "hello world を表示します",
Action: helloAction,
},
}
  • Nameでコマンド名を指定します。
  • Action: helloActionの中が処理本体です。指定したhelloAction関数にコマンドの処理を書いていきます。
グローバルオプションの処理
グローバルオプションの設定
グローバルオプションの設定はサンプルアプリ内のこちらのコードで実装しています。
// グローバルオプション設定
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "dryrun, d", // 省略指定 => d
Usage: "グローバルオプション dryrunです。",
},
}
  • グローバルオプションの指定は、app.Flagsに記述します。
  • この例ではcli.BoolFlag という形で、デフォルトfalseのBoolean型のオプションを設定しています。その他のFlagの種類は、cliパッケージのドキュメントを参照してください。StringFlag, IntFlagあたりはよく使います。cliパッケージのREADME.mdも参考になると思います。
グローバルオプションの利用
グローバルオプションの利用は、サンプルアプリ内のこちらのコードで実装しています。
// グローバルオプション
var isDry = c.GlobalBool("dryrun")
if isDry {
fmt.Println("this is dry-run")
}
  • cliのコンテキスト*cli.Context型の変数の中にc.GlobalBool, c.GlobalStringなどのグローバルオプションの型を指定して返す関数があるので、これを利用します。
パラメータの利用
パラメータの利用は、サンプルアプリ内のこちらのコードで実装しています。
if len(c.Args()) > 0 {
paramFirst = c.Args().First() // c.Args()[0] と同じ意味
}
  • パラメータはc.Args()を実行すると値が配列で返ってきます。
  • 値を取り出すには、c.Args()[0]のように配列のインデックスを指定します。値は文字列型で返ってきます。
おわりに
本稿では、Go言語のコマンドラインツールの簡単な実装方法について解説しました。

今回紹介したcodegangsta/cliなどの外部パッケージを用いることで、手間なく開発を進めることができます。



Go言語の基本文法に不安な方は、Sixeightさんの「シュッと golang に入門する話」が参考になると思います。

何を作っていいのやら・・・という方のために、今回のサンプルアプリとは別に、Slackへテキストを送信するコマンドラインツールを作ってみました。

こちらのコードでは、個人的に最近好きなtomlを使っています。Go言語勉強の手始めにしてみてください!