Finalizing the Cobra-generated Application

Now, let's finalize our demo applications and use the Cobra generator's configuration file.

Using the Cobra generator configuration file

When generating a lot of commands you often have to repeat the same arguments like license and author. Cobra provides a configuration file where you can set all these options just once. The default configuration file is: ~/.cobra.yaml. Here is an example configuration file for the choices we made for the calculator application:

author: Gigi
license: none

Adding pre-run and post-run Hooks

When you build larger applications, there are often various cross-cutting concerns like logging and instrumentation that you may want to perform for all commands. For example, run some code before each command, and run some other code after each command. You can add the code to do it in each command, but it is not very ergonomic. Some languages like Python provide syntactic structures like decorators that address this need. Go with its minimalist philosophy, doesn’t have this capability. Therefore, Cobra fills this gap with pre-run and post-run hooks.

There are two flavors of hooks: persistent and non-persistent. The order of execution is:

  • PersistentPreRun
  • PreRun
  • Run
  • PostRun
  • PersistentPostRun

The persistent hooks run for the command they are defined on and all its descendants. The non-persistent hooks run only for the commands they are defined on. In particular, if you want some code to run before/after each and every command then define the PersistentPreRun and PersistentPostRun functions on the root command.

For example, let’s measure the duration of each command execution and print it to the screen after the result. We need to add persistent hooks to the root command. In the PersistentPreRun command we store the current time in a variable called startTime. In the PersistentPostRun, we print the difference between the current time and the start time.

var startTime time.Time

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "calc-app",
	Short: "Calculate arithmetic expressions",
	Long: `Calculate arithmetic expressions.
           
           It can add integers and subtract integers`,
    PersistentPreRun: func(cmd *cobra.Command, args []string) {
    	startTime = time.Now()
	},
	PersistentPostRun: func(cmd *cobra.Command, args []string) {
		fmt.Printf("duration: %s	\n", time.Now().Sub(startTime))
	},
}

Let’s see it in action. It takes only about 20 to 24 microseconds to add or subtract two integers using our calculator application:

$ ./calc-app add 6 19
25
duration: 20.117µs

$ ./calc-app subtract 777 444
333

$ ./calc-app add 6 1
7
duration: 21.461µs

$ ./calc-app add 6 13
19
duration: 24.433µs

Try it yourself in the application below:

Get hands-on with 1200+ tech skills courses.