Golang urfave.cli:手动设置Flag不生效,如何正确构建Context?
问题
我们有一个应用,其中的runApp函数接收urfave cli的context对象:
import "gopkg.in/urfave/cli.v1" func runApp(ctx *cli.Context) { cache := ctx.GlobalInt(MyFlag.Name) // 执行更多操作 }
尝试不通过完整的CLI流程,直接从代码中调用runApp,手动构建ctx:
func MyTest() { fs := flag.NewFlagSet("", flag.ExitOnError) app := cli.NewApp() fs.Set(MyFlag.Name, "5000") ctx := cli.NewContext(app, fs, nil) runApp(ctx) }
但实际Flag似乎从未被设置,runApp无法读取手动设置的值,请问哪里操作错误?这种方式是否可行?
解答
这种方式是可行的,问题出在未将MyFlag注册到应用的全局Flag集合中,导致cli框架无法识别该Flag。
错误原因
urfave/cli的Context读取Flag时,会校验Flag是否已注册到App或Command的Flag集合内。你直接在底层flag.FlagSet设置值,但未让cli框架感知到该Flag的存在,因此ctx.GlobalInt只会返回默认值,而非你设置的5000。
修复方法
方法一:注册Flag到底层FlagSet并关联App
func MyTest() { // 初始化FlagSet并注册MyFlag fs := flag.NewFlagSet("", flag.ExitOnError) // 假设MyFlag是cli.IntFlag类型,需匹配其类型注册到底层FlagSet fs.Int(MyFlag.Name, MyFlag.Value.(int), MyFlag.Usage) // 将MyFlag添加到App的全局Flag集合 app := cli.NewApp() app.Flags = []cli.Flag{MyFlag} // 设置Flag值 fs.Set(MyFlag.Name, "5000") // 构建Context并调用runApp ctx := cli.NewContext(app, fs, nil) runApp(ctx) }
方法二:直接使用Context的GlobalSet方法(更简洁)
无需手动操作底层flag.FlagSet,直接通过Context的API设置全局Flag:
func MyTest() { app := cli.NewApp() // 先将MyFlag注册到App的全局Flag集合 app.Flags = []cli.Flag{MyFlag} // 创建Context后直接设置全局Flag ctx := cli.NewContext(app, nil, nil) ctx.GlobalSet(MyFlag.Name, "5000") runApp(ctx) }
两种方法都能让runApp正确读取到你设置的Flag值。
内容的提问来源于stack exchange,提问作者unsafe_where_true
相关产品推荐
相关产品推荐

