Golang如何实现先传入命令行位置参数再传入flags参数
解决Golang标准flag包无法解析后置flag的问题
根因说明
Go标准库flag的默认解析逻辑遵循传统Unix约定:解析参数时只要遇到第一个非-开头的参数,就会停止解析flag,后续所有内容都会被判定为位置参数。这就是-o放在位置参数后面时无法被识别的原因。
解决方案
方案一:使用pflag库(最简单兼容方案)
pflag是Go生态通用的参数解析库,完全兼容标准flag的API,同时原生支持GNU风格的参数规则,允许flag出现在命令行的任意位置,替换成本极低。
修改后代码如下:
package main import ( "fmt" "github.com/spf13/pflag" ) func main() { var output string pflag.StringVar(&output, "o", "", "Writes output to the file specified") pflag.Parse() fmt.Println("Positional Args : ", pflag.Args()) fmt.Println("Flag -o : ", output) }
修改后两种参数输入顺序都可以正常解析出-o的值和位置参数。
方案二:纯标准库实现(无第三方依赖)
如果不想引入外部依赖,可以手动调整命令行参数的顺序,将所有flag及对应值移到位置参数前面再交给标准flag.Parse()解析,示例代码如下:
package main import ( "flag" "fmt" "os" ) func main() { var output string flag.StringVar(&output, "o", "", "Writes output to the file specified") var flagArgs, positionalArgs []string for i := 1; i < len(os.Args); i++ { currArg := os.Args[i] // 识别flag参数 if len(currArg) > 1 && currArg[0] == '-' { flagName := currArg[1:] flagArgs = append(flagArgs, currArg) // 非布尔类型flag需要携带参数值,取下一个参数加入flag参数列表 if !isBoolFlag(flagName) && i+1 < len(os.Args) { flagArgs = append(flagArgs, os.Args[i+1]) i++ } } else { positionalArgs = append(positionalArgs, currArg) } } // 重组参数列表,flag在前,位置参数在后 os.Args = append([]string{os.Args[0]}, append(flagArgs, positionalArgs...)...) flag.Parse() fmt.Println("Positional Args : ", flag.Args()) fmt.Println("Flag -o : ", output) } // 判断指定flag是否为布尔类型 func isBoolFlag(name string) bool { f := flag.Lookup(name) if f == nil { return false } return f.DefValue == "true" || f.DefValue == "false" }
内容的提问来源于stack exchange,提问作者Mohit
相关产品推荐
相关产品推荐

