pflag
POSIX/GNU形式のフラグをサポートするGoライブラリ。Goの標準flagパッケージのドロップイン代替品です。
フレームワーク
pflag
概要
pflagは、POSIX/GNU形式のフラグをサポートするGoライブラリです。Goの標準flagパッケージのドロップイン代替品として設計されており、より柔軟なフラグ処理が可能です。Cobraと組み合わせて使用されることが多く、モダンなCLIアプリケーションの構築に適しています。
詳細
pflagは、標準のflagパッケージでは提供されないPOSIX/GNU形式のコマンドラインフラグを扱うために開発されました。--flag
(長い形式)と-f
(短い形式)の両方をサポートし、標準のflagパッケージと互換性を保ちながら、より豊富な機能を提供します。spf13/cobraライブラリの内部でも使用されており、Goエコシステムで広く採用されています。
主な特徴
- POSIX/GNU準拠:
--flag
と-f
形式の両方をサポート - ドロップイン代替: 標準flagパッケージの直接的な置き換えが可能
- 豊富なフラグタイプ: String、Int、Bool、Duration、Sliceなど多様な型に対応
- ショートハンド: 単一文字のエイリアスを定義可能
- FlagSet: 独立したフラグセットによるサブコマンドサポート
- カスタムフラグ: pflag.Valueインターフェースによる独自フラグ型の実装
- 互換性: 標準flagパッケージで定義されたフラグの組み込みが可能
メリット・デメリット
メリット
- 標準的なフラグ形式: POSIX/GNU規約に準拠した親しみやすいインターフェース
- 高い互換性: 既存のflagコードからの移行が容易
- 柔軟性: 様々なフラグタイプとカスタマイズオプション
- エコシステム: Cobraなど他のCLIライブラリとの優れた統合
- 軽量: 最小限のオーバーヘッドで高機能を提供
デメリット
- 単独利用: 単体では高度なCLI機能(サブコマンド、ヘルプ生成)は限定的
- 学習コスト: 標準flagから移行する際の微細な違い
- 依存関係: 外部ライブラリへの依存が発生
- 複雑な構造: 大規模なCLIには追加のフレームワークが必要
主要リンク
書き方の例
package main
import (
"fmt"
"os"
"github.com/spf13/pflag"
)
func main() {
// 基本的なフラグ定義
var name = pflag.String("name", "World", "あなたの名前")
var age = pflag.IntP("age", "a", 0, "あなたの年齢") // ショートハンド 'a'
var verbose = pflag.BoolP("verbose", "v", false, "詳細出力を有効にする")
var tags = pflag.StringSlice("tags", []string{}, "タグのリスト")
// ヘルプとバージョンフラグ
var help = pflag.BoolP("help", "h", false, "ヘルプを表示")
var version = pflag.Bool("version", false, "バージョンを表示")
// フラグの解析
pflag.Parse()
// ヘルプ表示
if *help {
pflag.Usage()
return
}
// バージョン表示
if *version {
fmt.Println("myapp version 1.0.0")
return
}
// フラグ値の使用
fmt.Printf("こんにちは、%s!\n", *name)
if *age > 0 {
fmt.Printf("あなたは%d歳です。\n", *age)
}
if *verbose {
fmt.Println("詳細出力が有効です。")
fmt.Printf("タグ: %v\n", *tags)
}
// フラグ以外の引数
if pflag.NArg() > 0 {
fmt.Printf("残りの引数: %v\n", pflag.Args())
}
}
// FlagSetを使用したサブコマンドの例
func withFlagSet() {
// メインコマンドのフラグ
mainFlags := pflag.NewFlagSet("main", pflag.ExitOnError)
debug := mainFlags.Bool("debug", false, "デバッグモードを有効にする")
// サブコマンド用のFlagSet
createFlags := pflag.NewFlagSet("create", pflag.ExitOnError)
createName := createFlags.String("name", "", "作成するリソースの名前")
createType := createFlags.String("type", "default", "リソースのタイプ")
deleteFlags := pflag.NewFlagSet("delete", pflag.ExitOnError)
deleteForce := deleteFlags.Bool("force", false, "強制削除")
deleteName := deleteFlags.String("name", "", "削除するリソースの名前")
// メインフラグの解析
mainFlags.Parse(os.Args[1:])
if *debug {
fmt.Println("デバッグモードが有効です")
}
// サブコマンドの処理
args := mainFlags.Args()
if len(args) == 0 {
fmt.Println("サブコマンドを指定してください: create, delete")
return
}
switch args[0] {
case "create":
createFlags.Parse(args[1:])
fmt.Printf("リソース作成: 名前=%s, タイプ=%s\n", *createName, *createType)
case "delete":
deleteFlags.Parse(args[1:])
if *deleteForce {
fmt.Printf("強制削除: %s\n", *deleteName)
} else {
fmt.Printf("削除: %s\n", *deleteName)
}
default:
fmt.Printf("不明なサブコマンド: %s\n", args[0])
}
}