🚀

Golang製CLIツールのすすめ

2022/12/20に公開

Golangの使い方がよくわからないという方々,いかがお過ごしでしょうか

ワタシ「(さて,Golang Advent Calendarの記事を書き始めたはいいけれど,いかんせんテーマの選定が難しい.とりあえずこの間作ったツールを紹介していく方向はいいけれど,これを紹介するだけだとなんか宣伝しに来た奴みたいで格好がつかないよな...)」
ワタシ「(とりあえず前置きが必要だよな...)」

Go言語,巷ではサーバーに用いられる言語として人気で,トップエンジニア学生の考える「これから挑戦してみたい(学んでみたい)プログラミング言語(複数選択)」では堂々の1位を飾りました[1].しかし,サーバーで用いられるということで取っ掛かりの難しい言語かもしれません.実際,同調査の「普段もっとも使っている or 好きなプログラミング言語(単一回答)」では7位,割合にしてたった2.8%しかいないのです.

そこで,今回私は Hello? Golang な方々への第一歩として,CLIツールの作成を提案しつつ,この間作った私のCLIツールを紹介していこうと思います.

なぜGo言語なのか

CLIツールを作るという話の前に,事前知識として,Go言語が多くの場面で使われるようになった背景です.もうすでに色々な方々が言及されているのでここでは簡単に箇条書きで整理します.

  • 文法が単純
    • 継承がなく,タプルなどの表現がない.内包するデータに対して定義する構造体と,内包する関数に対して要求するインターフェイスしかない
    • そもそも書きやすくするための糖衣構文が少ないため(読みやすくという観点では後述するフォーマッタなどの恩恵の方が大きい),記述する内容に対してコードが一意に定まる
    • 読みにくいコードを書く方が難しい言語であるため,標準ライブラリやOSSの実装も読み物として最適
  • 言語機能だけで痒い所に手が届く
    • 元々バックエンド用を謳う言語であるため,辞書型などのスクリプト言語の言語機能にありがちなものが言語機能として提供されている
    • さらに,Go言語は言語機能である go func() による並行処理と chan によるプロセス間通信が実現できてしまう(私がほかの言語に移動できない最大要因である)
  • ライブラリ選定・ツール選定で悩まされることが少ない
    • gofmtgodocなどの公式ツールが充実している
    • 特に公式でフォーマッタが提供されていることによってフォーマットで争う必要がないなど,ツール選定による悩みが少ない
    • 標準ライブラリもかなり充実しているのでライブラリ選定による悩みも少ない
    • サードパーティのライブラリも取得が簡単で pkg.go.dev から公開パッケージのドキュメントなどを探しに行ける
  • コンパイル言語であるため実行速度が速い
    • 当たり前だが,コンパイル言語なので解釈実行しているスクリプト言語よりも速い(これが前提)
    • 最近のコンパイル言語にありがちだが,その場でサクッとビルドして実行もできて,クロスプラットフォーム対応も行っているのでコンパイル言語のデメリットを感じる機会が少ない
    • それどころかインポートしたライブラリがバイナリとして含まれているので「実行環境にライブラリが入ってないから実行できない」みたいなことが少ない

なぜCLIツールなのか

Go言語は [go.dev/ref/spec] でも示されている通り, a general-purpose language と説明されている通り,様々な場面で使えるプログラミング言語です.であるにもかかわらず,なぜゲームやサーバーではなくCLIツールをGo言語への第一歩として推すのか,という点について初めに整理していきます.

  • 目的ができて,完成した実感が持てる
  • お金がかからない
  • 何を目的にしても実現しやすい
  • コンパイル言語の割にスクリプト言語のように簡単に実行して試すことができる
  • 簡単にバイナリ化・頒布することができる

目的ができて,完成した実感が持てる

言うまでもなく,目的ができます.というよりも目的を作りやすいです.プログラムを作っている最中に感じた不便な事に対して自動化するだけでも十分だと思います.完成したときはつまりツールがツールとして機能して便利になる瞬間なので実感も持ちやすいです.

お金がかからない

前述した「実感を持てる」のアンチパターンで一定数の人に見られるのですが,この言語は確かにバックエンド向けなので最初にAPIサーバーを書かせがちです.しかし,実際問題,APIサーバー作ったところで,ローカルで動かして localhost で叩けても何も楽しくありません.しかしながらIaaSを使うことはお金もかかり躊躇う人が多いと思います(私もその口だった).ですが,CLIツールであればローカルで実行する事こそが目的なのでその心配もいりません.

何を目的にしても実現しやすい

Go言語はシンプルなプロダクトをシンプルに作ることが得意なコンパイル言語で,言語機能や標準ライブラリも充実しており,サードパーティのライブラリも取得が簡単です.そのため,いい感じの開発・実行時間でやりたいと思ったことが割と簡単にできます.

簡単にバイナリ化・頒布することができる

Go言語は go install コマンドを使用するだけでパブリックリポジトリにあるツールをインストールすることができ,ご丁寧にもドキュメントを pkg.go.dev 内に作成してくれます.そのため,開発環境でないマシンにインストールしたり,ドキュメントを整理することはGoのエコシステム(言葉あってるかな?)の前においては低い障壁です.また,クロスプラットフォームで動作してインポートしたバイナリも実行バイナリ内に含まれているので実行環境のライブラリに依存することが少ないのもポイントが高いです.

サンプル的に作ってみました

今回,一例として簡単なCLIツールを作ってみました.Githubにあるので,そちらを見てもらえればと思います.

https://github.com/streamwest-1629/exec-onchanges

これはファイルの変更を検知して,それに対してコマンドを実行する[onchange]のようなプログラムです.まあ,せっかく作ったからには挙動に若干の差異があります.

通常のonchangeでは,ファイルを保存したときに実行されたコマンドによって書き換えられたファイルも追跡対象です.そのため,ファイル同期を行うようなコマンドにおいて,変更されたと勘違いして交互に呼び出し合う,という問題がありました.

今回作成したプログラムでは, 「開発する際にエンジニアが行う保存頻度なんてたかが知れている」 という考え方で,コマンド実行中のファイル変更を無視することで交互に呼び出し合う問題を解決しました.

本来,これはjupytextをVSCode Jupyterで扱うために開発していたのですが(.py.ipynb, .md間でファイル同期を行う必要があったが,通常のonchangeを使うと,片方を変更するともう片方もそれに呼応して永遠に保存しあう関係になってしまった),今回のAdvent Calendarに合わせて仰々しく綺麗に書き直しました(結構, context の扱い方とか合ってるかなぁという気持ちもあったりするので何か見つけたら報告していただけると幸いです).

まとめ

今回は,Goの初めの第一歩にCLIツールが良いという話をしました.かくいう私自身も,はじめてちゃんとGolangで開発して完成したモノはCLIツールでした.そのこともあって,第一歩にお薦めさせていただきました.皆様も快適なGoライフを!

脚注
  1. https://prtimes.jp/main/html/rd/p/000000008.000045025.html ↩︎

Discussion