概述
- 官方文档地址
- 接收命令行传参
- 给出友好的提示信息
- 推荐这样传参:
--name=yky --age=20
- 主要分为
flag
和 flagSet
, flag
使用 flag
底层实现是 flagSet
, flagSet
的默认命名是脚本名
方法清单
flag 和 flagSet 共有
- 数字相关:
flag.Int()
, flag.Int64()
, flag.IntVar()
, flag.Int64Var()
, flag.Uint()
, flag.Uint64()
, flag.UintVar()
, flag.Uint64Var()
, flag.Float64()
, flag.Float64Var()
- 布尔值相关:
flag.Bool()
, flag.BoolVar()
- 字符串相关:
flag.String()
, flag.StringVar()
- 时长相关:
flag.Duration()
, flag.DurationVar()
-
flag.Parse()
: 解析命令行参数(使用方法略有不同, flagSet 调用需要传入参数切片) -
flag.Lookup()
: 查找指定命名的 flag 变量, 存在返回*flag.Flag
, 不存在返回nil
-
flag.PrintDefaults()
: 输出帮助信息 -
flag.Var()
: 定义 -
flag.Set()
: 修改 -
flag.NFlag()
: 被命令行设置的 flag 参数的数量 - 非 flag 变量相关
-
flag.NArg()
: 非 flag 参数个数 -
flag.Args()
: 非 flag 参数列表 -
flag.Arg()
: 根据索引取非 flag 参数内容
-
flag.Parsed()
: 判断是否执行过 Parse()
flagSet 独有
-
fs.NewFlagSet()
: 初始化一个 flagSet -
fs.Init()
: -
fs.SetOutput
: 设置输出的位置, 参数类型为 io.Writer
使用
flag 示例
// 实际 flag 的底层实现是依据 flagSet, flagSetName 是脚本名
package main
import (
"flag"
"fmt"
)
func main() {
// 1. 先定义一个对应类型的变量, 将指针作为参数传给 <type>Var 方法
// StringVar(接收指针, 参数名, 默认值, 参数说明)
var name string
flag.StringVar(&name, "name", "yky", "姓名")
// 2. 直接注册一个flag变量(返回的是指针)
// Int(参数名, 默认值, 参数说明)
age := flag.Int("age", 18, "年龄")
// 解析命令行参数
flag.Parse()
// 注意输出时的不同, 一个是直接输出, 一个是指针转值
fmt.Printf("name: %v, age: %v\n", name, *age)
}
flagSet 示例
package main
import (
"flag"
"fmt"
)
func main() {
// 先注册一个 flagSet
fs := flag.NewFlagSet("main", flag.ExitOnError)
// 使用方法同上, 只是由 flagSet 调用
var name string
fs.StringVar(&name, "name", "yky", "姓名")
age := fs.Int("age", 18, "年龄")
// 这里不同, 需要传入参数范围, 也就是传参时指定--name和--age的索引
// 示例中[1:]表示解析所有
fs.Parse(os.Args[1:])
fmt.Printf("name: %v, age: %v\n", name, *age)
}
进阶示例
时长示例
package main
import (
"flag"
"fmt"
"time"
)
func main() {
// 时长示例: 可以接收参数 s(秒), m(分), h(小时)
sleep := flag.Duration("sleep", 1*time.Second, "延迟执行时间")
// 解析命令行参数
flag.Parse()
// 打印信息
fmt.Printf("sleeping for %v...\n", *sleep)
// 执行
time.Sleep(*sleep)
}
lookup (配合类型断言)
package main
import (
"flag"
"fmt"
)
func main() {
flag.Int("age", 18, "年龄")
flag.Parse()
// lookup 返回一个 *flag.Flag
if flag.Lookup("age") != nil {
// 此时 v 是一个 Value
// Value 是一个 Interface, 包括两个方法
// - String() string
// - Set(string) error
v := flag.Lookup("age").Value
// 可以通过 String(), 将结果完全转换为 string
fmt.Printf("%T: %[1]v\n", v.String())
// 也可以通过 (flag.Getter).(type) 转为对应的类型
// interface.(flag.Getter) 找到外层的接口
// .Get() 调用接口实现的方法
// .(type) 配合类型断言
y := v.(flag.Getter).Get()
// 已知类型的写法
z1 := y.(int)
fmt.Printf("%T: %[1]v\n", z1)
// 类型断言的标准写法
z2, ok := y.(int)
if ok {
fmt.Printf("%T: %[1]v\n", z2)
}
}
}
其他
// Parsed(), 返回 bool, 验证是否执行了 Parse()
flag.Parsed()
// 设置 flag 值, 内部会将参数转换为对应类型
flag.Lookup("age").Value.Set("190")
// 获取 flag 值
flag.Lookup("age").Value.String()
// NFlag(), 输出被解析的参数个数
fmt.Printf("是否解析命令行参数: %v, 解析匹配个数: %v\n", flag.Parsed(), flag.NFlag())
// NArg: 非 flag 指定的参数个数
if flag.NArg() == 0 {
fmt.Println("没有额外参数")
else {
// Args: 非 flag 指定的参数列表
fmt.Printf("额外参数列表: %v\n", flag.Args())
// Arg: 根据索引取非 flag 参数值
fmt.Printf("取索引为 0 的参数作为示例: %v\n", flag.Arg(0))
}
// Usage() 就是输出这个信息(--help)
flag.PrintDefaults()
源码
var
// 使用 flag.xxx 注册变量时, 会通过 CommandLine 调用 NewFlagSet 先定义 flagSet
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
// 用于打印帮助信息的方法, os.Args[0]即脚本名, 也是默认的 flagSet 的默认名W
var Usage = func() {
fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
PrintDefaults()
}
struct
// A Flag represents the state of a flag.
type Flag struct {
Name string // name as it appears on command line
Usage string // help message
Value Value // value as set
DefValue string // default value (as text); for usage message
}
// Flag names must be unique within a FlagSet. An attempt to define a flag whose
// name is already in use will cause a panic.
type FlagSet struct {
// Usage is the function called when an error occurs while parsing flags.
// The field is a function (not a method) that may be changed to point to
// a custom error handler. What happens after Usage is called depends
// on the ErrorHandling setting; for the command line, this defaults
// to ExitOnError, which exits the program after calling Usage.
Usage func()
name string
parsed bool
actual map[string]*Flag
formal map[string]*Flag
args []string // arguments after flags
errorHandling ErrorHandling
output io.Writer // nil means stderr; use Output() accessor
}
Interface
// 实现 String 和 Set 方法的就是 Value
// String 可以使内容类型变为 string
type Value interface {
String() string
Set(string) error
}
// 比 Value 多实现一个 Get 方法
type Getter interface {
Value
Get() interface{}
}
func
// 用 float64 举例
// -- float64 Value
type float64Value float64
func newFloat64Value(val float64, p *float64) *float64Value {
*p = val
return (*float64Value)(p)
}
func (f *float64Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 64)
if err != nil {
err = numError(err)
}
*f = float64Value(v)
return err
}
func (f *float64Value) Get() interface{} { return float64(*f) }
func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |