Search code examples
go-cobra

Why is Cobra flags not working in this code


How to get flags to work in Cobra using Local flags

package main

import (
    "fmt"
    "github.com/spf13/cobra"
)

func main() {
    myCmd := &cobra.Command{
        Use: "myaction",
        Run: func(cmd *cobra.Command, args []string) {
            if len(args) == 1 {
                flags := cmd.Flags()
                var strTmp string
                flags.StringVarP(&strTmp, "test", "t", "", "Source directory to read from")
                fmt.Println(strTmp)
            }
        },
    }

    myCmd.Execute()
}

Error

go run main.go myaction --test="hello"
Error: unknown flag: --test
Usage:
  myaction [flags]

Flags:
  -h, --help   help for myaction

Solution

  • The Run part of the command gets executed only after the Execute is called on the command (you can also have a prerun-hook.)

    So in your case when execute is called the runtime doesn't know about the flag. We should add the flags before the Execute is called on the command to make the runtime aware of it.

    Code

    package main
    
    import (
        "fmt"
    
        "github.com/spf13/cobra"
    )
    
    func main() {
        var strTmp string
        myCmd := &cobra.Command{
            Use: "myaction",
            Run: func(cmd *cobra.Command, args []string) {
                if len(args) == 1 {
                    fmt.Println(strTmp)
                }
            },
        }
        myCmd.Flags().StringVarP((&strTmp), "test", "t", "", "Source directory to read from")
        myCmd.Execute()
    }
    

    Output

    ⇒  go run main.go myaction --test "hello"
    hello
    

    But there is an alternate solution to this, when you want to add the flags based on a condition. You can set DisableFlagParsing to true and parse it later.

    Code

    package main
    
    import (
        "fmt"
    
        "github.com/spf13/cobra"
    )
    
    func main() {
        myCmd := &cobra.Command{
            Use: "myaction",
            RunE: func(cmd *cobra.Command, args []string) error {
                if len(args) > 1 {
                    flags := cmd.Flags()
                    var strTmp string
    
                    // Add the flag
                    flags.StringVarP(&strTmp, "test", "t", "", "Source directory to read from")
                    
                    // Enable the flag parsing
                    cmd.DisableFlagParsing = false
    
                    // Parse the flags
                    if err := cmd.ParseFlags(args); err != nil {
                        return err
                    }
    
                    fmt.Println(strTmp)
                }
    
                return nil
            },
        }
    
        // Disable flag parsing
        myCmd.DisableFlagParsing = true
        myCmd.Execute()
    }
    

    Output

    ⇒  go run main.go myaction --test "hello"
    hello