GoでのCLIツール開発は手軽ですが、機能が増えるとフラグ管理が煩雑になります。プロフェッショナルなCLIツールには、サブコマンド、柔軟な設定、分かりやすいヘルプ機能が不可欠です。この課題を解決するのが、CobraとViperの組み合わせです。
bash1go install github.com/spf13/[email protected] 2mkdir myapp && cd myapp 3go mod init myapp 4cobra-cli init
go1// cmd/root.go 2package cmd 3 4import ( 5 "fmt" 6 "log" 7 "os" 8 "github.com/spf13/cobra" 9 "github.com/spf13/viper" 10) 11 12var cfgFile string 13 14var rootCmd = &cobra.Command{ 15 Use: "myapp", 16 Run: func(cmd *cobra.Command, args []string) { 17 fmt.Printf("Host: %s, Port: %d\n", 18 viper.GetString("host"), viper.GetInt("port")) 19 }, 20} 21 22func Execute() { 23 if err := rootCmd.Execute(); err != nil { 24 os.Exit(1) 25 } 26} 27 28func init() { 29 cobra.OnInitialize(initConfig) 30 rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file") 31 rootCmd.PersistentFlags().String("host", "localhost", "server host") 32 rootCmd.PersistentFlags().Int("port", 8080, "server port") 33 34 viper.BindPFlag("host", rootCmd.PersistentFlags().Lookup("host")) 35 viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")) 36}
go1func initConfig() { 2 if cfgFile != "" { 3 viper.SetConfigFile(cfgFile) 4 } else { 5 home, _ := os.UserHomeDir() 6 viper.AddConfigPath(home) 7 viper.SetConfigName(".myapp") 8 viper.SetConfigType("yaml") 9 } 10 11 viper.SetEnvPrefix("MYAPP") 12 viper.AutomaticEnv() 13 14 if err := viper.ReadInConfig(); err != nil { 15 if _, ok := err.(viper.ConfigFileNotFoundError); ok { 16 fmt.Println("No config file found") 17 } else { 18 log.Fatalf("Config error: %v", err) 19 } 20 } 21}
設定ファイル例(~/.myapp.yaml
):
yaml1host: "0.0.0.0" 2port: 9090
設定値は以下の優先順位で決定されます:
MYAPP_HOST=localhost
)bash1cobra-cli add version 2cobra-cli add server
これでmyapp version
やmyapp server
コマンドが追加できます。
プロダクションレベルのCLIツールには、自動ビルド・配布が不可欠です。
yaml1# .github/workflows/release.yml 2name: Release 3on: 4 push: 5 tags: ["v*"] 6jobs: 7 release: 8 runs-on: ubuntu-latest 9 steps: 10 - uses: actions/checkout@v4 11 - uses: actions/setup-go@v4 12 with: 13 go-version: '1.21' 14 - uses: goreleaser/goreleaser-action@v5 15 with: 16 version: latest 17 args: release --rm-dist 18 env: 19 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
goreleaser設定例(.goreleaser.yaml
):
yaml1builds: 2 - env: [CGO_ENABLED=0] 3 goos: [linux, windows, darwin] 4 goarch: [amd64, arm64] 5 6archives: 7 - format: tar.gz 8 name_template: >- 9 {{ .ProjectName }}_ 10 {{- title .Os }}_ 11 {{- if eq .Arch "amd64" }}x86_64 12 {{- else if eq .Arch "386" }}i386 13 {{- else }}{{ .Arch }}{{ end }} 14 15release: 16 github: 17 owner: your-username 18 name: your-repo
go1// cmd/root_test.go 2package cmd 3 4import ( 5 "bytes" 6 "testing" 7 "github.com/spf13/viper" 8) 9 10func TestRootCommand(t *testing.T) { 11 viper.Set("host", "testhost") 12 viper.Set("port", 3000) 13 14 buf := new(bytes.Buffer) 15 rootCmd.SetOut(buf) 16 rootCmd.SetArgs([]string{}) 17 18 if err := rootCmd.Execute(); err != nil { 19 t.Fatalf("Execute failed: %v", err) 20 } 21 22 output := buf.String() 23 if !strings.Contains(output, "testhost") { 24 t.Errorf("Expected output to contain 'testhost', got: %s", output) 25 } 26}
CobraとViperの組み合わせにより、保守性が高く、ユーザーフレンドリーなCLIツールを効率的に開発できます。サブコマンド、設定ファイル、環境変数を統合的に管理し、プロフェッショナルなツール開発を実現しましょう。
私たちGoForceは、Goのコーディングスキルだけでなく、CobraやViperといったエコシステムのベストプラクティスを熟知し、プロフェッショナルなツールを開発できるエンジニアを高く評価しています。あなたのその「作る力」を、多くのユーザーに影響を与えるプロジェクトで活かしませんか?ぜひ一度、ご相談ください。
最適なGo案件を今すぐチェック!