Golang命令行参数解析指南

Golang命令行参数解析指南 我有以下标志定义:

outPtr := flag.String("o", "path", "PATH to save file")
findPtr := flag.String("f", "find", "find sentences with that word")
flag.Parse()

为什么当我向 -f 标志传递像 “word” 这样的值时,它能正确接收该字符串,但对于 -o 标志却总是使用默认字符串 “path”,而忽略我传入的任何字符串?我需要一些帮助来理解这个问题。

18 回复

谢谢!

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


感谢您的帮助 @calmh @NobbZ

这是两个选项且没有位置参数,所以没问题。

哦,我忘记推送代码了。现在代码已经上传。我正在构建一个最小示例来展示给你。

当然,可以通过使用不同的命令行解析器来实现。我喜欢 kingpin

我们需要如何运行它才能实际看到您的问题,还需要满足哪些其他前提条件?

能否提供一个完全可运行的示例,让我们可以在本地构建和运行,以展示您遇到的具体问题?也许可以包括一些终端运行的示例,包含它们的输出和期望的输出?

但这是以下要求:

./flags -f with -o ~/test.txt 

应该返回包含单词"with"的句子所生成的test.txt文件。

我有这个文件。内容如下:

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

查看代码

使用 Go 的 flags 包时,您需要在位置参数之前提供选项。也就是说,不是使用“flags list -o …”而是像您使用 -f 时那样使用“flags -o … list”。

calmh:

这是两个选项且没有位置参数,所以没问题。

我又来了:有没有可能实现先传递位置参数的需求?比如:

./binary list -o ~/test.txt

从 flag 包的文档中:

标志解析会在第一个非标志参数(“-”就是一个非标志参数)之前停止,或者在终止符“–”之后停止。

所以你需要在命令之前提供标志。

我没有看到任何与标志 o 相关的内容。只有 f。

请分享一个最小的可复现问题的代码。

一个单独的最小主包,包含所有内容,一个真正的sscce

问题出现在当你提供 -o 标志后跟字符串时。示例中的字符串是 ~/test.txt,但程序会采用在以下代码中指定的默认"路径":

outPtr := flag.String("o", "path", "PATH where the file is written at")

NobbZ:

标志解析会在第一个非标志参数前停止

那么,总结来说总是先解析选项,之后flag.Parse()函数会停止解析。因此,必须先传递像-f-o这样的参数,然后再传递所有非选项参数。 这样理解对吗?

flag.Parse()
./flags --> 无返回结果
./flags 2 --> 返回第2条语句
./flags -f with --> 返回包含"with"单词的语句
./flags list --> 返回所有语句
./flags list -o ~/test.txt --> 应在~/目录下生成名为text.txt的文件,内容为./flags list的输出

以下是我的代码位置:

GitHub GitHub

头像

eduartua/go-cli-app

go-cli-app - 构建基础Go命令行应用

参数和标志包括:

  • env(打印环境变量)
  • -f “字符串” → 打印包含该字符串的谚语
  • -o “路径” 应将内容写入指定路径的文件中

问题是当使用-o标志时,它只是使用了默认字符串:

outPtr := flag.String("o", "path", "PATH to save file")

即"path",所以它会在代码目录中创建一个名为path的文件。

问题出在 flag.String 函数的默认值参数上。当您使用 -o 标志时,传入的字符串被解释为新的默认值,而不是覆盖默认值。这是因为 flag 包在解析时会检查参数格式,而默认值中的空格可能导致解析问题。

以下是修正后的代码示例:

package main

import (
    "flag"
    "fmt"
)

func main() {
    // 使用空字符串作为默认值,避免与参数解析冲突
    outPtr := flag.String("o", "", "PATH to save file")
    findPtr := flag.String("f", "", "find sentences with that word")
    flag.Parse()
    
    // 检查是否提供了 -o 参数
    if *outPtr == "" {
        // 如果没有提供 -o 参数,使用默认路径
        *outPtr = "default_path"
    }
    
    fmt.Printf("Output path: %s\n", *outPtr)
    fmt.Printf("Find word: %s\n", *findPtr)
}

运行示例:

go run main.go -o "/user/custom/path" -f "searchword"

输出:

Output path: /user/custom/path
Find word: searchword

关键点:

  1. 避免在默认值中使用可能被解析为标志的字符串
  2. 使用空字符串作为默认值,然后在代码中处理默认逻辑
  3. 确保命令行参数格式正确:-flag value-flag=value

这样修改后,-o 标志就能正确接收您传入的字符串值了。

回到顶部