Writing to STDOUT and STDERR
It's fairly common to use fmt.Println
to print output to the user. Both
Println
and Printf
will actually print to os.Stdout
for us, and so it
serves as a convenience function for hacking on some code quickly, and getting
some text in front of the user.
ref
Cobra commands actually provide some wiring for printing things to the user via
Stdout or Stderr that allows us to configure its outputs to write to anything
that fulfills the io.Writer interface (e.g. log files, byte buffers, etc). We
don't need to concern ourselves with that quite yet, but what we do want to do
instead of using fmt.Println
is use the built-in output for stdout/stderr if
we need them.
In our sumCommandRunE
, we write the sum using fmt.Println
:
func sumCommandRunE(cmd *cobra.Command, args []string) error { // return an error
// convert args which is []string to []int
values := make([]int, len(args))
for i, v := range args {
vAsInt, err := strconv.Atoi(v)
if err != nil { // new code!
return fmt.Errorf("you provide a value that was not an integer: %s", v)
}
values[i] = vAsInt
}
fmt.Println(sum(values...)) // Writes happen here!
return nil
}
Instead, lets leverage the output target configured for the command. In fairness, we haven't reconfigured it in this example, but we can, and that will become more important when testing your cobra commands.
Change the line to look like this:
// fmt.Println(sum(values...)) // Old!
fmt.Fprintln(cmd.OutOrStdout(), sum(values...))
If you're not familiar with Fprintln, it effectively allows you to provide the
write target (the io.Writer
interface) instead of assuming it should be
os.Stdout, as fmt.Println
does. In this instance, we're passing in the cobra
command's configured writer. It, internally, will write to os.Stdout if nothing
else was configured.
We don't use it here, but there's an equivalent cmd.OutOrStderr
function as
well.
If you run the command, nothing should have changed.
$ go build -o math . && ./math sum 1 3
4