ZhangZhihui's Blog  

 root.go:

func init() {
    rootCmd.PersistentFlags().BoolVarP(&enableLogging, "log", "l", true, "Logging information")
    fmt.Println("*************************", enableLogging)
}

func Execute() {
    err := rootCmd.Execute()
    fmt.Println("@@@@@@@@@@@@@@@@@@@@@@@@@", enableLogging)
    if err != nil {
        os.Exit(1)
    }
}

 

zzh@ZZHPC:/zdata/Github/mastering-go-expertise/stats_cli$ go run main.go insert -f d4.txt --log=false
************************* true
time=2024-06-23T23:27:37.700+08:00 level=ERROR msg="Invalid value a in line 0 strconv.ParseFloat: parsing \"a\": invalid syntax\n"
time=2024-06-23T23:27:37.700+08:00 level=ERROR msg="Invalid value b in line 1 strconv.ParseFloat: parsing \"b\": invalid syntax\n"
time=2024-06-23T23:27:37.700+08:00 level=ERROR msg="Invalid value c in line 2 strconv.ParseFloat: parsing \"c\": invalid syntax\n"
time=2024-06-23T23:27:37.700+08:00 level=ERROR msg="Invalid value d in line 3 strconv.ParseFloat: parsing \"d\": invalid syntax\n"
failed to read at least one value
@@@@@@@@@@@@@@@@@@@@@@@@@ false

 

rootCmd.Execute() runs below functions in order:

    // The *Run functions are executed in the following order:
    //   * PersistentPreRun()
    //   * PreRun()
    //   * Run()
    //   * PostRun()
    //   * PersistentPostRun()
    // All functions get the same args, the arguments after the command name.
    // The *PreRun and *PostRun functions will only be executed if the Run function of the current
    // command has been declared.
    //
    // PersistentPreRun: children of this command will inherit and execute.
    PersistentPreRun func(cmd *Command, args []string)
    // PersistentPreRunE: PersistentPreRun but returns an error.
    PersistentPreRunE func(cmd *Command, args []string) error
    // PreRun: children of this command will not inherit.
    PreRun func(cmd *Command, args []string)
    // PreRunE: PreRun but returns an error.
    PreRunE func(cmd *Command, args []string) error
    // Run: Typically the actual work function. Most commands will only implement this.
    Run func(cmd *Command, args []string)
    // RunE: Run but returns an error.
    RunE func(cmd *Command, args []string) error
    // PostRun: run after the Run command.
    PostRun func(cmd *Command, args []string)
    // PostRunE: PostRun but returns an error.
    PostRunE func(cmd *Command, args []string) error
    // PersistentPostRun: children of this command will inherit and execute after PostRun.
    PersistentPostRun func(cmd *Command, args []string)
    // PersistentPostRunE: PersistentPostRun but returns an error.
    PersistentPostRunE func(cmd *Command, args []string) error

 

To be precise, flags have been parsed before running the above functions:

root.go:

var rootCmd = &cobra.Command{
    Use:   "stats",
    Short: "Statistics application",
    Long:  `The statistics application`,
    PersistentPreRun: func(cmd *cobra.Command, args []string) {
        fmt.Println("Starting rootCmd.PersistentPreRun")
        fmt.Println("#########################", enableLogging)
        setDefaultLogger()
    },
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("Starting rootCmd.Run")
        fmt.Println("$$$$$$$$$$$$$$$$$$$$$$$$$", enableLogging)
    },
}

func init() {
    fmt.Println("Starting root.init()")
    rootCmd.PersistentFlags().BoolVarP(&enableLogging, "log", "l", true, "Logging information")
    fmt.Println("*************************", enableLogging)
}

func setDefaultLogger() {
    logger = slog.New(slog.NewTextHandler(os.Stderr, nil))
    if !enableLogging {
        logger = slog.New(slog.NewTextHandler(io.Discard, nil))
    }
    slog.SetDefault(logger)
}

func Execute() {
    fmt.Println("Starting rootCmd.Execute()")
    err := rootCmd.Execute()
    fmt.Println("@@@@@@@@@@@@@@@@@@@@@@@@@", enableLogging)
    if err != nil {
        os.Exit(1)
    }
}

 

insert.go:

var insertCmd = &cobra.Command{
    Use:   "insert",
    Short: "insert command",
    Long:  `A longer description of the insert command.`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("Starting insertCmd.Run")
        insertRun()
    },
}

func init() {
    fmt.Println("Starting insert.init()")
}

 

zzh@ZZHPC:/zdata/Github/mastering-go-expertise/stats_cli$ go run main.go insert -f d4.txt
Starting insert.init()
Starting root.init()
************************* true
Starting rootCmd.Execute()
Starting rootCmd.PersistentPreRun
######################### true
Starting insertCmd.Run
time=2024-06-24T11:18:25.280+08:00 level=ERROR msg="Invalid value a in line 0 strconv.ParseFloat: parsing \"a\": invalid syntax\n"
time=2024-06-24T11:18:25.280+08:00 level=ERROR msg="Invalid value b in line 1 strconv.ParseFloat: parsing \"b\": invalid syntax\n"
time=2024-06-24T11:18:25.280+08:00 level=ERROR msg="Invalid value c in line 2 strconv.ParseFloat: parsing \"c\": invalid syntax\n"
time=2024-06-24T11:18:25.280+08:00 level=ERROR msg="Invalid value d in line 3 strconv.ParseFloat: parsing \"d\": invalid syntax\n"
failed to read at least one value
@@@@@@@@@@@@@@@@@@@@@@@@@ true
zzh@ZZHPC:/zdata/Github/mastering-go-expertise/stats_cli$ go run main.go insert -f d4.txt --log=false Starting insert.init() Starting root.init() ************************* true Starting rootCmd.Execute() Starting rootCmd.PersistentPreRun ######################### false Starting insertCmd.Run failed to read at least one value @@@@@@@@@@@@@@@@@@@@@@@@@ false

 

Function setDefaultLogger assign different values to a global variable logger according to the value of persistent flag enableLogging. The right place to call it is the PersistentPreRun field of rootCmd.

The function in the Run field of rootCmd does not run when executing a specific command.

posted on 2024-06-23 23:43  ZhangZhihuiAAA  阅读(15)  评论(0)    收藏  举报