What is go in options


It has been edited slightly for readability. I want to begin my talk with a story.

what is go in options

It is lateyour company is launching a revolutionary new distributed social network. Wisely, your team has chosen Go as the language for this product. You have been tasked with writing the crucial server component. Possibly it looks a little like this. There are some unexported fields that need to be initialised, and a goroutine must be started to service incoming requests.

The package has a simple API, it is pretty easy to use. But, there is a problem. Soon after you announce your first beta release, the feature requests start to roll in.

In this climate of heightened security awareness, your bug tracker starts to fill with demands to support secure connections. Then, you get a report from a user who is running your server on a very small VPS. They need a way to limit the number of simultaneous clients.

Functional options for friendly APIs

Next is the request to rate limit concurrent connections from a group of users being targeted by a botnet. Now, you need to change your API to incorporate all these feature requests. Show of special option, who has used an API like this? Who has written an API like this?

-$127,000 Robinhood Negative Balance Options Trading [Robinhood App Buying Power Mess Up]

Who has had their code break while depending on an API like this? Obviously this solution is cumbersome and brittle. Newcomers to your package have no idea which parameters are optional, and which are mandatory. If not, what do I provide instead?

Functional options on steroids

Do I use zero? Zero sounds reasonable, but depending on how the feature was implemented, that might limit you to zero total concurrent connections. While this example could be a considered an exaggeration, maliciously constructed and compounded by poor documentation, I believe that it demonstrates a real issue with ornate, brittle APIs such as this.

Rather than trying to provide one single function which must cater for every permutation, a solution might be to create a set of functions. With this approach, when callers need a secure server they can call the TLS variant.

{ Soham Kamani }

When they need to establish a maximum duration for idle connections, they can use the variant that takes a timeout. Unfortunately, as you can see, providing every possible permutation can quickly become overwhelming. A very common solution is to use a configuration struct.

This has some advantages. Using this approach, the configuration struct can grow over time as new options are added, while the public API for creating a server itself remains unchanged. This method can lead to better documentation.

This post is about the practices that appeared around the pattern since it was first introduced. Functional options came to life as a way to create nice and clean APIs with configuration, specifically involving optional settings. There are many obvious ways to do it constructor variants, config struct, setter methods, etcbut they fall short when a package has a dozen options and don't produce nearly as nice APIs as functional options do. Recap - What are functional options?

What was once a massive comment block on the NewServer function, becomes a what is go in options documented struct. Potentially it also enables the callers to use the zero value to signify they they want the default behaviour for a particular configuration option.

However, this pattern is not perfect. It has trouble with defaults, especially if the zero value has a well understood meaning.

Most of the time, users of your API will be expecting to use its default behaviour.

Using functional options instead of method chaining in Go

Even though they do not intend to change any of the configuration parameters, tricky strategies for binary options callers are still required to pass something for that second argument.

Why should users of your API be required to construct an empty value, simply to satisfy the signature of the function? A common solution to this empty value problem is to pass a pointer to the value instead, thereby enabling callers to use nil rather than constructing an empty value.

what is go in options

In my opinion this pattern has all the problems of the previous example, and it adds a few more. It raises the question, is there a difference between passing nil, and passing a pointer to an empty value? Which gives rise to questions of what happens if this value is mutated after being passed to the NewServer function?

I believe that well written APIs should not require callers to create dummy values to satisfy those rarer use cases. I believe that we, as Go programmers, should work hard to ensure that nil is never a parameter that needs to be passed to any public function.

  • Functional options for friendly APIs – The acme of foolishness
  • go - The Go Programming Language

And when we do want to pass configuration information, it should be as self explanatory and as expressive as possible. So now with these points in mind, I want to talk about what I believe are some better solutions.

what is go in options

To remove the problem of that mandatory, yet what is go in options unused, configuration value, we can change the NewServer function to accept a variable number of arguments. And in my book this solves two big problems.

First, the invocation for the default behaviour becomes as concise as possible.