I wanted to know if there's a way to exclude flag values that aren't set by the user from cli. So my problem is, I have some optional flags in my cobra cmd
that have default values. I wonder if there's a way to exclude these optional flags if they aren't set by the user from being processed? Or in another perspective, is there a way to extract flags that are changed by the user explicitly from cli from a cmd
flagset?
Here's an example to better illustrate my case:
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())
So suppose for age and address, I want them to be optional and not propagated when they're passed to struct. So this means, in the cli, the user is not required to submit the age
and address
flags and the default values for these optional flags are nil. However, Int & String flags are strongly typed, so they require default values (eg: ""
and -1
). As a result, when I bind the command pflags to viper and user don't input age & address values in the cli, viper will receive ""
for address and -1
for age. Using the above method, the default values will get propagated to the User struct.
What I want is, to exclude flag values that aren't set by the user. Is there a way for me to exclude User struct from receiving flag values that aren't explicitly set by the user?
My current solution to exclude the unset flags from being processed in the User struct is currently like this:
- Have an array of the command flags. Initialize an empty
map[string]interface{}
- Iterate through the array, and check if the flag is set/changed via
flags.Changed("flag")
. If flag is changed, then add it to map - Convert map to json
Unmarshal json object to struct
// 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)
But I was wondering if there is a better alternative than my solution above. Preferably, I don't want to change anything in the User
struct as it is imported from an external package.
Thank you. Your help is greatly appreciated.