Kingpin
Goのコマンドライン引数パーサー。流暢なインターフェースとPOSIX/GNU規約のサポートが特徴です。
フレームワーク
Kingpin
概要
Kingpinは、Goのコマンドライン引数パーサーです。流暢なインターフェース(Fluent Interface)とPOSIX/GNU規約のサポートが特徴です。シンプルで直感的なAPIを提供し、複雑なコマンドライン構造を簡単に構築できます。現在はメンテナンスモードとなっており、新規プロジェクトでは他の選択肢が推奨されています。
詳細
Kingpinは長年にわたってGoコミュニティで使用されてきた実績のあるCLIライブラリです。流暢なインターフェースにより、可読性の高いコマンド定義が可能で、多くのオープンソースプロジェクトで採用されました。しかし、現在は積極的な開発が終了し、メンテナンスモードに移行しています。新しいプロジェクトでは、より活発に開発されているcobraやurfave/cliの使用が推奨されています。
主な特徴
- 流暢なインターフェース: メソッドチェーンによる直感的なAPI
- POSIX/GNU規約サポート: 標準的なコマンドライン規約に準拠
- サブコマンド: 階層的なコマンド構造をサポート
- カスタムバリデーション: 独自の値検証ロジックの実装が可能
- シェル補完: Bash、Zsh、Fish、PowerShellでの補完をサポート
- 環境変数サポート: フラグのデフォルト値を環境変数から取得
- ヘルプ生成: 自動的なヘルプメッセージとUsageの生成
メリット・デメリット
メリット
- 可読性: 流暢なインターフェースによる理解しやすいコード
- 豊富な機能: 本格的なCLIアプリケーションに必要な機能を網羅
- 標準準拠: POSIX/GNU規約に準拠した一貫性のある動作
- 柔軟性: カスタムバリデーションや値パーサーの実装が可能
- 実績: 多くのプロジェクトでの採用実績
デメリット
- メンテナンス状況: 現在はメンテナンスモードで新機能開発は停止
- コミュニティ: アクティブなコミュニティサポートが限定的
- 将来性: 長期的なサポートに不安がある
- 学習コスト: 新規プロジェクトでは他の選択肢の方が推奨される
主要リンク
書き方の例
package main
import (
"fmt"
"net"
"time"
"github.com/alecthomas/kingpin/v2"
)
var (
// グローバルフラグ
debug = kingpin.Flag("debug", "デバッグモードを有効にする").Bool()
timeout = kingpin.Flag("timeout", "ping待機のタイムアウト").
Default("5s").
Envar("PING_TIMEOUT").
Short('t').
Duration()
// 引数
ip = kingpin.Arg("ip", "ping先のIPアドレス").Required().IP()
count = kingpin.Arg("count", "送信するパケット数").Int()
)
func main() {
// バージョン設定
kingpin.Version("0.0.1")
// 引数をパース
kingpin.Parse()
// 実行
fmt.Printf("ping実行: %s (タイムアウト %s, 回数 %d)\n", *ip, *timeout, *count)
if *debug {
fmt.Println("デバッグモードが有効です")
}
}
// サブコマンドの例
func withSubcommands() {
var (
app = kingpin.New("chat", "コマンドライン チャットアプリケーション")
// グローバルフラグ
serverIP = app.Flag("server", "サーバーアドレス").Default("127.0.0.1").IP()
debug = app.Flag("debug", "デバッグモードを有効にする").Bool()
// registerコマンド
register = app.Command("register", "新しいユーザーを登録")
registerNick = register.Arg("nick", "ユーザーのニックネーム").Required().String()
registerName = register.Arg("name", "ユーザーの名前").Required().String()
// postコマンド
post = app.Command("post", "チャンネルにメッセージを投稿")
postChannel = post.Arg("channel", "投稿先チャンネル").Required().String()
postText = post.Arg("text", "投稿するテキスト").Strings()
postImage = post.Flag("image", "投稿する画像").File()
)
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
case register.FullCommand():
fmt.Printf("ユーザー登録: %s (%s)\n", *registerNick, *registerName)
case post.FullCommand():
fmt.Printf("チャンネル %s に投稿\n", *postChannel)
if *postImage != nil {
fmt.Println("画像付き投稿")
}
if len(*postText) > 0 {
fmt.Printf("メッセージ: %s\n", strings.Join(*postText, " "))
}
}
}