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.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律