Skip to content

Instantly share code, notes, and snippets.

@enjoylife
Last active March 10, 2019 05:07
Show Gist options
  • Save enjoylife/35bf50b3071811d259b59351332b3dfc to your computer and use it in GitHub Desktop.
Save enjoylife/35bf50b3071811d259b59351332b3dfc to your computer and use it in GitHub Desktop.
Practical example using functional options for creating extendable functions in Go(golang).
package main
import (
"flag"
"fmt"
)
// An ServerOption configures our Server
type ServerOption interface {
apply(s *Server) // 😈 an option is now ours and ours alone to implement
}
// optionFunc wraps a func so it satisfies the ServerOption interface.
type optionFunc func(*Server)
// apply satisfies the interface and
// invokes the optionFunc
func (f optionFunc) apply(s *Server) {
f(s)
}
// Use OptionHost to set the host the server will use.
func OptionHost(host string) ServerOption {
return optionFunc(func(s *Server) {
s.host = host
})
}
// Use OptionPort to set the port the server will use.
func OptionPort(port int) ServerOption {
return optionFunc(func(s *Server) {
s.port = port
})
}
// This is the type whose options you're enabling users to set.
type Server struct {
host string
port int
}
// This is your creator function that accepts a list of option functions.
func NewServer(opts ...ServerOption) *Server {
s := &Server{}
// call option functions on instance to set options on it
for _, opt := range opts {
opt.apply(s)
}
return s
}
func (s *Server) Addr() string {
return fmt.Sprintf("%s:%d", s.host, s.port)
}
func main() {
var host = flag.String("host", "127.0.0.1", "host")
var port = flag.Int("port", 3000, "port")
flag.Parse()
// This is how your user sets the options.
s := NewServer(
OptionHost(*host),
OptionPort(*port),
)
fmt.Printf("Server available at %s", s.Addr())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment