Go - Append behavior in option values using flag package

While working on the solutions to exercises for my soon to be published book Practical Go, I needed to implement a way to implement an option in my command line application which could be specified multiple times. The result would be that all the values specified would form a list of the values. To make that concrete, consider that you are writing a command line HTTP client application. You want to add one or more headers to an outgoing request, so this is the user interface that you want for your application:

$ my-command-line-app -header key1:value1 -header key2:value2 https://www.example.com

Next, I show how you can achieve the above using the Go standard library’s flag package.

The Func() function

The Func() function allows you to define a function that will be called everytime the flag parsing machinery encounters a specific option. This is how our solution to the above problem may look like:

type httpConfig struct {
	headers         []string
}

func myFunc() {
  c := httpConfig{}
  fs := flag.NewFlagSet("http", flag.ContinueOnError)	
  // define your other flags

  // define a header option that can be specified multiple
  // times and the values will be appended 
  headerOptionFunc := func(v string) error {
		c.headers = append(c.headers, v)
		return nil
	}
  fs.Func("header", "Add one or more headers to the outgoing request (key=value)", headerOptionFunc)
  
  # other stuff..
}

headerOptionFunc gets calld everytime the flag.Parse() function encounters -header. Here, we append it to a list headers which is a field we have defined in the httpConfig struct.

This is another of those moments, where I thought - how do i solve this using the standard library? (Yes i hear you, didn’t you think of that when you wrote the exercise? I may have, or i may not have, who knows).

And the standard library delivered, yet again.