devlog

[Go] cobra の Command.RunE はエラーを返せる

2024-01-29

概要

  • Go言語でコマンドラインツールを作るとき cobra というライブラリが便利
  • cobra では通常 Command.Run というフィールドにハンドラ (関数) をセットする
  • Command.Run のハンドラではエラーを返せない
  • Command.RunE というフィールドもあり、このハンドラではエラーを返せる

エラーが起きたら log.Fatal するしかない? という課題感

Command.Run のハンドラのシグネチャは func(cmd *Command, args []string) です。
Go言語あるあるな「エラーを返す」ということができません。

そのためエラーが起きたら log.Fatal して終わらせていたのですが、テストをしづらく課題に感じてました。

package main import ( "log" "github.com/spf13/cobra" ) func main() { cli := &cobra.Command{ Use: "samplecli", Version: "0.0.1", // エラーを返せない Run: func(cmd *cobra.Command, args []string) { if err := processData(); err != nil { log.Fatalf("Error: %s", err.Error()) } }, } cli.Execute() }

ところが cobra には Command.RunE というフィールドもあり、ここではエラーを返せることを知りました。

Command.RunE ではエラーを返せる

Command.RunE のハンドラのシグネチャは func(cmd *Command, args []string) error です。
エラーを返せます。

package main import ( "os" "github.com/spf13/cobra" ) func main() { cli := &cobra.Command{ Use: "samplecli", Version: "0.0.1", // エラーを返せる RunE: func(cmd *cobra.Command, args []string) error { if err := processData(); err != nil { return err } return nil }, } if err := cli.Execute(); err != nil { os.Exit(1) } }

エラーメッセージを出力してくれる

Command.RunE のハンドラでエラーを返すと cobra がエラーメッセージを出力します。

$ samplecli Error: failed to process data

この挙動は SilenceErrors で無効にできます。

cli.SilenceErrors = true

感想

正直好みの問題ですが私はエラーを返す方が自然に思え好きです。
テストをしやすくなりますし、エラーのたびに log.Fatal() を書くのも面倒かと思い。。

  • 作成日
    2024-01-29
  • 更新日
    2024-02-03