gocommand-line-interfaceflagsgo-cobra

Can you specify optional arguments to a flag in Cobra?


Let's say I have this flag in my program that only prints a positive number:

c.PersistentFlags().IntVar(&SomeFlag, optionSomeFlag, 0, "do something (range: x-y)")

The default is 0 so if the user doesn't toggle the flag, nothing is printed.

How can I make the flag accept arguments but have a default itself? i.e. if the default was 5

./program --someflag output would be 5

But if I did

./program --someflag=1 output would be 1

I tried following the user guide for Cobra and was expecting a command type that would allow me to specify default values only if the user triggers the flag, not just altogether. I may have misinterpreted this or missed something though.


Solution

  • It can be done using NoOptDefVal

    rootCmd.PersistentFlags().Lookup("someflag").NoOptDefVal = "5"
    

    In the following code, you can find a complete example of a command line application with cobra that have the behavior you describe

    package main
    
    import (
        "fmt"
        "github.com/spf13/cobra"
    )
    
    func main() {
        var someFlag int
        var defaultSomeFlag = "5"
    
        // Create the root command.
        rootCmd := &cobra.Command{
            Use:   "program",
            Short: "A brief description of your application",
            Long:  "A longer description of your application",
            Run: func(cmd *cobra.Command, args []string) {
                // Check whether the flag was explicitly set.
                if cmd.Flags().Lookup("someflag").Changed {
                    fmt.Printf("someflag: %d\n", someFlag)
                } else {
                    // If the flag was not explicitly set don't print a value.
                    fmt.Printf("someflag is not set\n")
                }
            },
        }
    
        // Define the flag and set its default value.
        rootCmd.PersistentFlags().IntVar(&someFlag, "someflag", 0, "do something (range: x-y)")
        rootCmd.PersistentFlags().Lookup("someflag").NoOptDefVal = defaultSomeFlag
    
        // Execute the root command.
        if err := rootCmd.Execute(); err != nil {
            fmt.Println(err)
        }
    }
    

    Below are the results of the execution with different flag values.

    $ ./test
    someflag is not set
    $ ./test --someflag
    someflag: 5
    $ ./test --someflag=3
    someflag: 3