Created
May 11, 2021 18:19
-
-
Save miroswan/b4e53795f962469e471902365a93030c to your computer and use it in GitHub Desktop.
Functional Variadic Arguments as Options
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"strings" | |
) | |
// consoleOptions is a private structure that contains | |
// the possible options for a Console. It's private so | |
// that consumers do not rely on its members. This allows | |
// the code to be able to be extended without breaking how | |
// consumers use it. | |
type consoleOptions struct { | |
lastNameOption string | |
shoutOption bool | |
} | |
// ConsoleOption is a functional option that can be passed | |
// to a constructor of a Console. Again, this allows the | |
// constructor of a Console to be extended without | |
// breaking the constructor function's signature. | |
type ConsoleOption func(*consoleOptions) | |
// LastNameConsoleOption can be passed to the Console's | |
// constructor function. It adds the last name to the console | |
// messages. | |
func LastNameConsoleOption(lastName string) ConsoleOption { | |
return func(options *consoleOptions) { | |
options.lastNameOption = lastName | |
} | |
} | |
// ShoutConsoleOption can be passed to the Console's | |
// constructor function. It makes each console | |
// message "loud" by making each message upper case. | |
func ShoutConsoleOption() ConsoleOption { | |
return func(options *consoleOptions) { | |
options.shoutOption = true | |
} | |
} | |
// NewConsole returns a pointer to a Console. Note that we | |
// can add an arbitrary number of options in the future | |
// without changing the signature of this constructor | |
// function. | |
func NewConsole( | |
firstName string, | |
optionFunctions ...ConsoleOption, | |
) *Console { | |
// load the options passed into the constructor | |
options := new(consoleOptions) | |
for _, function := range optionFunctions { | |
function(options) | |
} | |
// Return a pointer to Console, furnished with all | |
// of the required and optional configuration. | |
return &Console{ | |
firstName: firstName, | |
lastNameOption: options.lastNameOption, | |
shoutOption: options.shoutOption, | |
} | |
} | |
// Console prints messages to STDOUT with some additional information | |
type Console struct { | |
firstName string // required | |
lastNameOption string // optional | |
shoutOption bool // optional | |
} | |
// Print the message to STDOUT | |
func (c *Console) Print(message string) { | |
b := new(strings.Builder) | |
b.WriteString(c.firstName) | |
b.WriteRune(' ') | |
// If the lastNameOption is an empty string, then it was not set | |
if c.lastNameOption != "" { | |
b.WriteString(c.lastNameOption) | |
b.WriteRune(' ') | |
} | |
// If shoutOption is set, then upcase the message | |
b.WriteString(": ") | |
if c.shoutOption { | |
b.WriteString(strings.ToUpper(message)) | |
} else { | |
b.WriteString(message) | |
} | |
fmt.Println(b.String()) | |
} | |
func main() { | |
console := NewConsole( | |
"Pragmatic", // required argument | |
LastNameConsoleOption("Coder"), // optional configuration | |
ShoutConsoleOption(), // optional configuration | |
) | |
console.Print("This message has been customized.") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment