Golang命令行参数/标志的用法解析

Golang命令行参数/标志的用法解析 你好,我想使用命令行标志/参数。 例如:

MYSOFT -g FILE

使用 flags.String 时,它能正常工作,但如果我们没有在 -g 标志后传递任何参数,它会显示:

flag needs an argument: -g
Usage of ./MYSOFT:
  -g string
         (default "install")

我希望如果标志参数为空,它应该显示: 请提供一个参数以进行安装

实际上,我想要的是,如果有人运行 MYSOFT 命令,输出应该像这样:

Usage: <options> software

MYSOFT Options:
-i, --install, install     Install Software

 You must have the name of the software you want to install or update, so you can use this command.

如果有人运行 MYSOFT -i,那么输出应该像这样:

Please enter any software, the selected software doesn't exists

如果有人运行 MYSOFT -i CALCULATOR

it will execute some codes

我也尝试过通过 os.Args 来实现,但无论怎么做都不太对。 当我通过 fmt.Println 添加这些行时:

Usage: <options> software

MYSOFT Options:
-i, --install, install     Install Software

 You must have the name of the software you want to install or update, so you can use this command.

那么如果我运行 MYSOFT -i CALCULATOR,上面的字符串也会出现

有人知道该怎么做吗


更多关于Golang命令行参数/标志的用法解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html

9 回复

嗯,这相当困难且令人困惑。

更多关于Golang命令行参数/标志的用法解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


所以,我认为你需要寻找像这样的自定义标志解析器:https://github.com/cosiner/flag

问题依旧存在: 当你运行 go run . -i 并且不输入任何内容时,该命令会显示默认的帮助信息并以代码 2 退出。

gucio321:

我发现我的代码有个问题

如果你把默认字符串从 “default” 改成 “” 会怎样?

result.name = flag.String("i", "", "enter app name")

找到了解决方案。FlagSet 结构体包含一个类型为 func()Usage 字段。你可以在这里设置自己的用法信息,如下所示:

fs.Usage = func() {
	  fmt.Println("Usage: blah...")
}

哦,是的,是我的错。我把不带参数传递 -i 和完全不传递 -i 搞混了。

我猜对于自定义错误处理,使用 FlagSet 可能是一个解决方案。

func main() {
    fmt.Println("hello world")
}

哟! 也许像这样? 哦,好吧,我发现我的代码有个问题。

package main

import (
	"flag"
	"fmt"
)

type Flags struct {
	name *string
}

func parse() *Flags {
	result := &Flags{}
	result.name = flag.String("i", "default", "enter app name")
	flag.Parse()
	if *result.name == "" {
		fmt.Println("you must enter something")
	}

	return result
}

func main() {
	f := parse()
	fmt.Println(*f.name)
}

嗯,我觉得当没有提供标志值时,它仍然会打印 Usage()

我使用 FlagSet 的代码:

package main

import (
	"flag"
	"fmt"
	"os"
)

type Flags struct {
	name *string
}

func parse() *Flags {
	result := &Flags{}
	fs := flag.NewFlagSet("arguments", flag.ContinueOnError)
	result.name = fs.String("i", "default", "enter app name")
	if err := fs.Parse(os.Args[1:]); err != nil {
		fmt.Println(err)
		// return result
	}

	if *result.name == "" {
		fmt.Println("you must enter something")
	}

	return result
}

func main() {
	f := parse()
	fmt.Println(*f.name)
}

在Go中,你可以通过自定义flag.Usage函数和验证标志值来实现你的需求。以下是一个完整的示例:

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    // 自定义usage信息
    flag.Usage = func() {
        fmt.Fprintf(os.Stderr, "Usage: <options> software\n\n")
        fmt.Fprintf(os.Stderr, "MYSOFT Options:\n")
        fmt.Fprintf(os.Stderr, "  -i, --install, install     Install Software\n\n")
        fmt.Fprintf(os.Stderr, "You must have the name of the software you want to install or update, so you can use this command.\n")
    }

    // 定义标志
    installFlag := flag.String("i", "", "Install Software")
    flag.StringVar(installFlag, "install", "", "Install Software")

    // 解析标志
    flag.Parse()

    // 检查是否只运行了MYSOFT而没有参数
    if len(os.Args) == 1 {
        flag.Usage()
        return
    }

    // 检查-i标志是否被设置但值为空
    if *installFlag == "" && (flagIsSet("i") || flagIsSet("install")) {
        fmt.Println("Please enter any software, the selected software doesn't exists")
        return
    }

    // 如果有有效的软件名,执行安装逻辑
    if *installFlag != "" {
        fmt.Printf("Installing software: %s\n", *installFlag)
        // 这里添加你的安装代码
        // executeSomeCodes()
    }
}

// 辅助函数检查标志是否被设置
func flagIsSet(name string) bool {
    found := false
    flag.Visit(func(f *flag.Flag) {
        if f.Name == name {
            found = true
        }
    })
    return found
}

另一个更简洁的实现方式,使用flag.FlagSet

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    // 创建自定义的FlagSet
    fs := flag.NewFlagSet("MYSOFT", flag.ExitOnError)
    
    // 设置自定义usage
    fs.Usage = func() {
        fmt.Fprintf(os.Stderr, "Usage: <options> software\n\n")
        fmt.Fprintf(os.Stderr, "MYSOFT Options:\n")
        fmt.Fprintf(os.Stderr, "  -i, --install, install     Install Software\n\n")
        fmt.Fprintf(os.Stderr, "You must have the name of the software you want to install or update, so you can use this command.\n")
    }

    // 定义标志
    installFlag := fs.String("i", "", "Install Software")
    fs.StringVar(installFlag, "install", "", "Install Software")

    // 如果没有参数,显示usage
    if len(os.Args) == 1 {
        fs.Usage()
        return
    }

    // 解析参数
    err := fs.Parse(os.Args[1:])
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: %v\n", err)
        return
    }

    // 检查安装标志
    if (*installFlag == "" && (fs.Lookup("i").Changed || fs.Lookup("install").Changed)) {
        fmt.Println("Please enter any software, the selected software doesn't exists")
        return
    }

    // 执行安装逻辑
    if *installFlag != "" {
        fmt.Printf("Installing software: %s\n", *installFlag)
        // 这里添加你的安装代码
    }
}

测试示例:

  1. 运行 MYSOFT
Usage: <options> software

MYSOFT Options:
  -i, --install, install     Install Software

You must have the name of the software you want to install or update, so you can use this command.
  1. 运行 MYSOFT -i
Please enter any software, the selected software doesn't exists
  1. 运行 MYSOFT -i CALCULATOR
Installing software: CALCULATOR

这个实现通过自定义flag.Usage函数控制帮助信息的显示,使用flag.VisitFlagSet.Lookup().Changed来检查标志是否被设置,并在标志被设置但值为空时显示自定义错误信息。

回到顶部