golang flag库详解

原文链接:《golang flag库详解o》

golang flag库详解

flag 是 Go 标准库中用于命令行参数解析的库,适合用于 CLI 程序。它提供了简洁的接口来定义、解析和使用命令行标志(flags)。


一、基本使用

Go 中的命令行参数通常以如下格式传递:

./app -port=8080 -mode=debug

对应代码:

package main

import (
    "flag"
    "fmt"
)

func main() {
    port := flag.Int("port", 8080, "端口号")
    mode := flag.String("mode", "release", "运行模式")

    flag.Parse() // 解析命令行参数

    fmt.Println("port:", *port)
    fmt.Println("mode:", *mode)
}

输出

$ go run main.go -port=9090 -mode=debug
port: 9090
mode: debug

二、支持的数据类型

类型函数返回类型示例
flag.Bool*booldebug := flag.Bool("debug", false, "是否开启调试")
flag.Int*intport := flag.Int("port", 8080, "端口号")
flag.Int64*int64
flag.Uint*uint
flag.String*stringmode := flag.String("mode", "dev", "模式")
flag.Float64*float64
flag.Duration*time.Duration支持如 1s500ms 等格式

三、自定义变量(实现 flag.Value 接口)

type stringList []string

func (s *stringList) String() string {
    return fmt.Sprintf("%v", *s)
}

func (s *stringList) Set(value string) error {
    *s = append(*s, value)
    return nil
}

func main() {
    var names stringList
    flag.Var(&names, "name", "指定名称,可多次设置")

    flag.Parse()

    fmt.Println("names:", names)
}

调用方式:

$ go run main.go -name=张三 -name=李四
names: [张三 李四]

四、flag.Parse()flag.Args()flag.NArg()

flag.Parse()  // 解析命令行参数
flag.Args()   // 返回非 flag 参数(如命令后面跟的文件名)
flag.NArg()   // 返回 Args() 的数量
flag.NFlag()  // 返回设置了多少 flag

示例:

$ go run main.go -port=8080 config.yaml
flag.Args() => [config.yaml]
flag.NArg() => 1
flag.NFlag() => 1

五、flag 默认使用方式和 FlagSet

默认 FlagSet(flag.CommandLine

一般用 flag.Int, flag.String 等就是在 flag.CommandLine 上注册的。

自定义 FlagSet(适用于多个子命令)

fs := flag.NewFlagSet("server", flag.ExitOnError)
port := fs.Int("port", 8000, "端口")

fs.Parse(os.Args[2:])

适合像:

$ myapp server -port=8000
$ myapp client -host=localhost

六、帮助信息自动生成

只需在代码中定义 flag,然后在终端中执行:

$ go run main.go -h

会自动打印每个 flag 的说明。


七、常见问题

  • flag 必须在 flag.Parse() 前定义。
  • 不能支持 -abc 连写,需要 -a -b -c 分开写。
  • flag 不支持 POSIX 风格子命令解析(如 git commit -m),建议使用 spf13/cobra 等库。

下面是一个实际项目中使用 flag 管理配置的完整示例,用于模拟一个简单的 Web 服务器程序。该程序支持如下配置参数:

  • -port:监听端口(默认 8080
  • -mode:运行模式,支持 debug / release
  • -timeout:请求超时时间(默认 5s
  • -static:静态资源目录(默认 ./static

✅ 示例:main.go

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
)

type Config struct {
    Port      int
    Mode      string
    Timeout   time.Duration
    StaticDir string
}

func parseFlags() *Config {
    port := flag.Int("port", 8080, "监听端口")
    mode := flag.String("mode", "release", "运行模式:debug/release")
    timeout := flag.Duration("timeout", 5*time.Second, "请求超时时间,示例:3s, 500ms")
    static := flag.String("static", "./static", "静态资源目录")

    flag.Parse()

    return &Config{
        Port:      *port,
        Mode:      *mode,
        Timeout:   *timeout,
        StaticDir: *static,
    }
}

func main() {
    config := parseFlags()

    if config.Mode != "debug" && config.Mode != "release" {
        fmt.Println("mode 参数只能为 debug 或 release")
        os.Exit(1)
    }

    if config.Mode == "debug" {
        log.Printf("[调试模式] 当前配置: %+v\n", config)
    }

    mux := http.NewServeMux()

    // 静态资源处理
    fs := http.FileServer(http.Dir(config.StaticDir))
    mux.Handle("/", fs)

    // 创建带超时的服务器
    server := &http.Server{
        Addr:         fmt.Sprintf(":%d", config.Port),
        Handler:      mux,
        ReadTimeout:  config.Timeout,
        WriteTimeout: config.Timeout,
    }

    log.Printf("服务器启动中,监听端口:%d,模式:%s,静态目录:%s\n", config.Port, config.Mode, config.StaticDir)
    if err := server.ListenAndServe(); err != nil {
        log.Fatal("服务器启动失败:", err)
    }
}

✅ 运行示例

# 默认运行
$ go run main.go

# 指定端口和运行模式
$ go run main.go -port=9090 -mode=debug -timeout=10s -static=./public

输出:

[调试模式] 当前配置: &{Port:9090 Mode:debug Timeout:10s StaticDir:./public}
服务器启动中,监听端口:9090,模式:debug,静态目录:./public

✅ 配合系统服务使用

你还可以将其编译后作为系统后台服务使用:

$ go build -o myserver main.go
$ ./myserver -port=8081 -mode=release -timeout=2s

这个结构清晰、可扩展,如果你后期打算支持子命令、配置文件等,可以在此基础上引入 flag.FlagSet 或者 viper / cobra 等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值