英文:
Can I add commands with Go flags?
问题
我知道我可以像这样定义标志:
initPtr := flag.String("init", "config.json", "使用配置文件名进行初始化")
我会这样调用它:
myapp --init=myconfig.json
不过我想知道是否可以定义类似命令的东西,这样可以这样调用应用程序:
myapp init --filename=myconfig.json
myapp check --filename=myconfig.json
myapp run
英文:
I know I can define flags like this:
initPtr := flag.String("init", "config.json", "Initialize with config filename")
Which I will call like this:
myapp --init=myconfig.json
I wonder though if I can define something like commands so that to call the app like this?
myapp init --filename=myconfig.json
myapp check --filename=myconfig.json
myapp run
答案1
得分: 1
是的,你可以。
请查看https://golang.org/pkg/flag/获取FlagSet文档。
还有一个可工作的示例:https://github.com/constabulary/gb/blob/master/cmd/gb/main.go
以下是miltonb请求的示例:
%go run flagset.go init --filename=foo.json foo bar
init foo.json [foo bar]
%go run flagset.go check --filename=bar.json 1 2 3
check bar.json [1 2 3]
%go run flagset.go run
run
%cat flagset.go
package main
import (
    "flag"
    "fmt"
    "os"
)
func main() {
    init := flag.NewFlagSet("init", flag.ExitOnError)
    initFile := init.String("filename", "myconfig.json", "configuration file")
    check := flag.NewFlagSet("check", flag.ExitOnError)
    checkFile := check.String("filename", "myconfig.json", "configuration file")
    if len(os.Args) <= 1 {
        flag.Usage()
        os.Exit(1)
    }
    switch os.Args[1] {
    case "init":
        if err := init.Parse(os.Args[2:]); err == nil {
            fmt.Println("init", *initFile, init.Args())
        }
    case "check":
        if err := check.Parse(os.Args[2:]); err == nil {
            fmt.Println("check", *checkFile, check.Args())
        }
    case "run":
        fmt.Println("run")
    }
}
英文:
Yes, you can.
Take a look at https://golang.org/pkg/flag/ for FlagSet documentation.
And for a working example: https://github.com/constabulary/gb/blob/master/cmd/gb/main.go
And an example as requested by miltonb:
% go run flagset.go init --filename=foo.json foo bar
init foo.json [foo bar]
% go run flagset.go check --filename=bar.json 1 2 3
check bar.json [1 2 3]
% go run flagset.go run
run
% cat flagset.go
package main
import (
	"flag"
	"fmt"
	"os"
)
func main() {
	init := flag.NewFlagSet("init", flag.ExitOnError)
	initFile := init.String("filename", "myconfig.json", "configuration file")
	check := flag.NewFlagSet("check", flag.ExitOnError)
	checkFile := check.String("filename", "myconfig.json", "configuration file")
	if len(os.Args) <= 1 {
		flag.Usage()
		os.Exit(1)
	}
	switch os.Args[1] {
	case "init":
		if err := init.Parse(os.Args[2:]); err == nil {
			fmt.Println("init", *initFile, init.Args())
		}
	case "check":
		if err := check.Parse(os.Args[2:]); err == nil {
			fmt.Println("check", *checkFile, check.Args())
		}
	case "run":
		fmt.Println("run")
	}
}
答案2
得分: 1
你可以使用命令行参数和标志的组合来实现这一点。
例如:
configFilePtr := flag.String("filename", "", "配置文件名")
flag.Parse()
n := len(os.Args)
if n > 1 {
    switch os.Args[1] {
        case "init":
            initApp(*configFilePtr)
        case "check":
            checkApp(*configFilePtr)
        case "run":
            runApp()
    }
}
另一种选择是使用类似于 spf13's cobra 的工具。
更新:
如果你需要根据命令使用不同的标志,你可以使用 FlagSet,就像 Kare Nuorteva 的回答中提到的那样。
例如:
f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
silent := f1.Bool("silent", false, "")
f2 := flag.NewFlagSet("f2", flag.ContinueOnError)
loud := f2.Bool("loud", false, "")
switch os.Args[1] {
  case "apply":
    if err := f1.Parse(os.Args[2:]); err == nil {
      fmt.Println("apply", *silent)
    }
  case "reset":
    if err := f2.Parse(os.Args[2:]); err == nil {
      fmt.Println("reset", *loud)
    }
}
参考资料:
英文:
You can do that using a combination of command line arguments and flags.
Eg.
configFilePtr := flag.String("filename", "", "Config Filename")
flag.Parse()
n := len(os.Args)
if n > 1 {
    switch os.Args[1] {
        case "init":
            initApp(*configFilePtr)
        case "check":
            checkApp(*configFilePtr)
        case "run":
            runApp()
    }
}
Another option is using something like spf13's cobra.
Update :
If you require the use of different flags as per command you can use a FlagSet as mentioned in Kare Nuorteva's answer.
Eg.
f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
silent := f1.Bool("silent", false, "")
f2 := flag.NewFlagSet("f2", flag.ContinueOnError)
loud := f2.Bool("loud", false, "")
switch os.Args[1] {
  case "apply":
    if err := f1.Parse(os.Args[2:]); err == nil {
      fmt.Println("apply", *silent)
    }
  case "reset":
    if err := f2.Parse(os.Args[2:]); err == nil {
      fmt.Println("reset", *loud)
    }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论