如何仅提取在cli中显式设置的标志集?

时间:2019-01-26 15:23:28

标签: go go-cobra viper-go go-flag

我是cobraviper的新手。

我想知道是否有一种方法可以排除cli中用户未设置的标志值。所以我的问题是,我的眼镜蛇cmd中有一些带有默认值的可选标志。我想知道是否有一种方法可以排除如果用户未设置这些可选标志的情况?或者从另一个角度来看,是否有一种方法可以从cmd标志集中从cli中提取用户明确更改的标志?

这是一个更好地说明我的情况的例子:

var cmd = &cobra.Command{
    Use:   "command [operations]",
    Short: "Perform some commands",
    Run: func(cmd *cobra.Command, args []string) {
        var user User
        err := viper.Unmarshal(&user)
        fmt.Println(err)
        fmt.Println(user)
    },
}

cmd.PersistentFlags().String("name", "", "Your Name (Required)")
cmd.PersistentFlags().String("description", "", "Description")
cmd.PersistentFlags().String("address", "", "Address")
cmd.PersistentFlags().Int("age", -1, "Age")
cmd.MarkPersistentFlagRequired("name")
viper.BindPFlags(cmd.PersistentFlags()) 

所以假设年龄和地址,我希望它们是可选的,并且在传递给struct时不要传播。因此,这意味着在cli中,不需要用户提交ageaddress标志,并且这些可选标志的默认值为nil。但是,Int&String标志是强类型的,因此它们需要默认值(例如:""-1)。结果,当我将命令pflag绑定到viper且用户未在cli中输入年龄和地址值时,viper将收到""作为地址,-1作为年龄。使用上述方法,默认值将传播到User结构。

我想要的是排除用户未设置的标志值。我有什么办法可以将User结构排除在用户未明确设置的标志值之外?

我当前在User结构中排除未设置标志的当前解决方案是这样的:

  1. 具有命令标志的数组。初始化一个空的map[string]interface{}
  2. 遍历数组,并检查是否通过flags.Changed("flag")设置/更改了标志。如果标志已更改,则将其添加到地图
  3. 将地图转换为json
  4. 解组json对象以构造

    // inside the Run function of a cobra command
    aMap := make(map[string]interface{})
    flags := cmd.Flags()
    for _, flag := range cmdFlags {
        if flags.Changed(flag) {
            aMap[flag] = viper.Get(flag)
        }
    }
    jsonStr, _ := json.Marshal(aMap)
    var user User
    json.Unmarshal(jsonStr, &user)
    fmt.Println(user)
    

但是我想知道是否有比我上面的解决方案更好的选择。最好是,我不想更改User结构中的任何内容,因为它是从外部包中导入的。

谢谢。非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

假设您的User结构看起来像这样:

type User struct {
    ...
    age     int
    address string
    ...
}

然后默认情况下,User结构的初始化将设置age => 0, address => 0。因此,即使viper没有设置默认值。内部去吧。

我的建议是:
1.更改用户结构的创建方式

type User struct {
    ...
    age     *int
    address *string
    ...
}
  1. 将这两个字段的眼镜蛇默认值设置为nil
    这样,您将知道Cobra的默认设置是不设置该值。每当设置该值时,它将是非nil值。希望有帮助!