【Golang】go:embedを用いて格言表示コマンド(subaru)を開発

前書き:go:embedを試したかった

Golangでは、go:embedがVersion1.16から組み込まれています。

go:embedの利点は、「バイナリインストール(設定ファイルや関連ファイル含む)がより簡単になる事」でしょうか。go:embedを用いる事によって、バイナリの中に設定ファイルやスクリプトなどを埋め込めます。そのため、バイナリをシステムに置くだけで、インストール作業が完了となります。

この手法は、他言語でも一般的です。例えば、シェルスクリプトにバイナリを埋め込んで、インストーラを作る手法があります。

馴染み深いがゆえに、「go:embedを使ったコマンドを作ってみたいな」と2021年から考えていました。2022年の2月に重い腰を上げて、go:embedの勉強用コマンド(subaru)を作ることにしました。

       

subaru:格言を出力するfortuneライクコマンド

subaruコマンドは、fortuneコマンドをインスパイアしています。

fortuneとは、Unix系OSのコマンドの一つ。フォーチュン・クッキーを模したプログラムであり、歴史上の偉人の名言や有名人の発言などを一部引用したメッセージを無作為に表示する。

     

subaruコマンドをそのまま実行すると、ランダムで格言(および格言に関係する人、会社、ツールの名前)が表示されます。

サブコマンドが用意されており、特定の格言を出力できます。例えば、以下の例ではUnix哲学を出力します。

                   

設計:格言追加時にコードを修正しない

subaruコマンドを開発する時、避けたかった設計が一つあります。それは、subaruコマンドのコード内部に格言(テキスト)をベタ書きする方法です。コードはなるべく触りたくありません。

そのため、subaruコマンドは以下の設計となっています。

  • 格言は外部ファイル(拡張子”.subaru”)に定義する
  • 全ての*.subaruファイルをgo:embedでバイナリに組み込む
  • *.subaruファイルからサブコマンドを実行時に定義する
  • *.subaruファイルのファイル名をサブコマンド名とする

これらの仕様をどのように実装したかを後述します。

         

*.subaruファイルの埋め込み

subaruコマンドのディレクトリ構成(大事な部分)は、以下の構成です。

fortune/*以下に存在するファイルを全てバイナリに埋め込みます。そのため、プロジェクトルートディレクトリに存在するmain.goに、go:embedの処理を書いています。

埋め込みでは、初期化前の変数(上記の例ではfortune)の上に”//go:embed”を記載します。変数の型には、string、[]byte、embed.FSが使用できます。

“//go:embed    “の後に、埋め込み対象のファイル名を書きます。ファイル名はスペース区切りで複数記載でき、上記の例のようにワイルドカード指定もできます。

注意点は、「”//”と”go:embed”の間にスペースは不要」および「埋め込めないファイルが存在する事」です。後者の具体例ですが、”go:embed”を記載したファイルより上の階層のファイル」は埋め込めません。つまり、”//go:embed ../sample.txt”のような記載はビルドエラーとなります。

              

サブコマンドを実行時に定義

この方法は、エキスパートたちのGo言語の1.2章(依存関係のある処理を並行して実行できるタスクランナー)を真似して実装しました。

subaruコマンドはspf13/cobraを利用しています。サブコマンド定義は、cobraのAPI “ (*cobra.Command).AddCommand()”を呼び出せば終わります。

 

subaruコマンドの場合、上記のAddCommandに渡す引数は、サブコマンド名、サブコマンドの説明、サブコマンドのエントリーポイント関数の3つです。

  • サブコマンド名は、*.subaruのファイル名と同一
  • サブコマンドの説明は、”Print phrase related to $(サブコマンド名)”
  • エントリーポイント関数は、*.subaruの内容を標準出力に表示

上記の処理があるおかげで*.subaruファイルが増えても、自動でサブコマンドが定義されます(再ビルドは必須)。そのため、ファイル追加だけでドンドン格言が増やせます。コントリビュートしたい方、募集中!

          

最後に:subaruの由来

subaru(昴)は、子供に付けようと思った名前です。

昴は意味も良いし、車のSUBARUは技術大好きな人が多いし、名字との合わせも良くて「完璧だ」と思っていました。が、諸事情でNGとなりました。

一度気に入った名前なので「コマンドの名前にでもするか」と考え、今回subaruを実装しました。subaruは、集団(何かが集まるイメージ)の意味があるので「格言”集”」となっています。

                

 おまけ:2022年に作成したGolang製コマンド一覧

【Golang】2022年に開発した自作CLIコマンド/ライブラリに対する所感と宣伝【OSS】

おすすめ

1件の返信

  1. 2022年2月5日

    […] 【golang】go:embedを用いて格言表示コマンド(subaru)を開発 […]