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言語勉強の手始めにしてみてください!

  • このエントリーをはてなブックマークに追加

Recommend

Couplesの開発をスムーズにしてくれるbotの紹介 ~この世の理はすなわち速さだと思いませんか?~

Go言語でもくもくする会「ごもく会」第二回を開催しました