Functional Options Pattern in Go

Go

Functional Options Pattern (FOP) is a Go idiom for giving a function optional parameters with sensible defaults. Go has no keyword-level support for default parameters, so we can do that behavior using a first-class function.

What we want to achieve

I usually write TypeScript, so here’s a quick example for comparison.

type Curry = {
  rice: string;
  powder: string;
  spice?: string
};
 
function createCurry(
  rice: string,
  powder: string,
  spice?: string
) {
  return {
    rice,
    powder,
    spice,
  };
}
 
const curry1 = createCurry("あきたこまち", "ジャワカレー");
console.log({ curry1 });
 
const curry2 = createCurry("コシヒカリ", "バーモントカレー", "クミン");
console.log({ curry2 });

Example

If we translate the same example into Go, we can use FOP like this.

type Curry struct {
	rice   string
	powder string
	spice  *string
}
 
type Option func(*Curry)
 
func NewCurry(rice string, powder string, opts ...Option) *Curry {
	curry := &Curry{
		rice:   rice,
		powder: powder,
	}
	for _, opt := range opts {
		opt(curry)
	}
 
	return curry
}
 
func WithSpice(spice string) func(*Curry) {
	return func(c *Curry) {
                 s := spice
		c.spice = &s
	}
}
 
func main() {
	curry1 := NewCurry("あきたこまち", "ジャワカレー")
	fmt.Printf("curry1: %v", curry1)
 
	curry2 := NewCurry("コシヒカリ", "バーモントカレー", WithSpice("クミン"))
	fmt.Printf("curry2: %v", curry2)
}