Skip to content

Instantly share code, notes, and snippets.

@sirenko
Last active June 28, 2021 23:10
Show Gist options
  • Save sirenko/505f3ca3ea20ef71c9d2f44961658a48 to your computer and use it in GitHub Desktop.
Save sirenko/505f3ca3ea20ef71c9d2f44961658a48 to your computer and use it in GitHub Desktop.
// Design Pattern: functional options
//
// Go playground URL: https://play.golang.org/p/FiUmbyqEZgd
//
// References:
// Rob Pike, Self-referential functions and the design of options: https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
// Dave Cheney; Functional options for friendly APIs: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
// Functional options on steroids, Márk Sági-Kazár: https://sagikazarmark.hu/blog/functional-options-on-steroids/
package main
import (
"errors"
"fmt"
"os"
"strconv"
)
type Client struct {
ID int
Name string
}
type ClientOptionFunc func(*Client) error
func NewClient(options ...ClientOptionFunc) (*Client, error) {
c := &Client{}
for _, option := range options {
if err := option(c); err != nil {
return nil, err
}
}
return c, nil
}
func SetID(id int) ClientOptionFunc {
return func(c *Client) error {
if id < 1024 {
return errors.New("the ID is too small, less than 1024")
}
c.ID = id
return nil
}
}
func SetName(name string) ClientOptionFunc {
return func(c *Client) error {
c.Name = name
return nil
}
}
func (c *Client) String() string {
return strconv.Itoa(c.ID) + "/" + c.Name
}
func main() {
c, err := NewClient(
SetID(10024),
SetName("myClient"))
if err != nil {
fmt.Printf("failed to create a client: %v", err)
os.Exit(1)
}
fmt.Println(c)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment