Check out the optional.go
file for more details on the usage.
Last active
January 24, 2023 10:08
-
-
Save thexpand/1bfcdf89192f2947c29ade17bd0647c2 to your computer and use it in GitHub Desktop.
Go: Optional parameters
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 ( | |
"example/optional" | |
"fmt" | |
) | |
func main() { | |
say("world") | |
say("hello", SayArgs{withExclamationMark: optional.Arg(true)}) | |
} | |
type SayArgs struct { | |
milliseconds *optional.ArgType[int] | |
withExclamationMark *optional.ArgType[bool] | |
} | |
func say(s string, args ...SayArgs) { | |
opts := optional.GetOpts(&args) | |
milliseconds := optional.Get(opts.milliseconds, 100) | |
withExclamationMark := optional.Get(opts.withExclamationMark, false) | |
if withExclamationMark { | |
s = fmt.Sprint(s, "!") | |
} | |
fmt.Println(s) | |
} |
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 optional deals with cases where you would like to have optional arguments for a function. | |
package optional | |
// ArgType is used to define optional arguments of a function. | |
// Typically, the type function will have the optional arguments | |
// that are defined as a struct, placed as a last argument(s) of the function. | |
// An example: | |
// | |
// type MyFunctionArgs struct { | |
// someInt *optional.ArgType[int] | |
// someBool *optional.ArgType[bool] | |
// } | |
// | |
// func MyFunction(someRequiredString string, args ...MyFunctionArgs) {} | |
type ArgType[T any] struct { | |
Value T | |
} | |
// Arg is used in function calls to pass optional arguments. | |
// It returns a pointer to an ArgType that is expected by the function with optional arguments. | |
// | |
// If the function uses a struct to hold the optional arguments | |
// you could pass them and use optional.Arg(value) to pass a different | |
// value for the function instead of the default one. | |
// | |
// Here's an example: | |
// MyFunction("some required string", MyFunctionArgs{someBool: optional.Arg(true)}) | |
// | |
// There is no need to provide the generic type, as it can be inferred | |
// from the value you pass as an argument to this function. | |
func Arg[T any](Value T) *ArgType[T] { | |
return &ArgType[T]{Value} | |
} | |
// GetOpts transforms the slice argument of the variadic function (taking only | |
// the first item from the slice) into a single args struct instance. | |
// If the slice is empty, then an empty struct instance will be returned. | |
// | |
// An example of the usage inside a function: | |
// | |
// func MyFunction(someRequiredString string, args ...MyFunctionArgs) { | |
// opts := optional.GetOpts(&args) | |
// } | |
func GetOpts[T any](opts *[]T) *T { | |
if len(*opts) > 0 { | |
return &(*opts)[0] | |
} | |
var empty T | |
return &empty | |
} | |
// Get returns a default value or the one from the option if it's not nil. | |
// Here is a full example of a function that has its optional arguments | |
// defined as a struct and how the default values are provided. | |
// | |
// type MyFunctionArgs struct { | |
// someInt *optional.ArgType[int] | |
// someBool *optional.ArgType[bool] | |
// } | |
// | |
// func MyFunction(someRequiredString string, args ...MyFunctionArgs) { | |
// opts := optional.GetOpts(&args) | |
// someInt := optional.Get(opts.someInt, 100) | |
// someBool := optional.Get(opts.someBool, false) | |
// } | |
// | |
// There is no need to provide the generic type, as it can be inferred | |
// from the option (from the struct) and from the type of the defaultValue. | |
func Get[T any](option *ArgType[T], defaultValue T) T { | |
if option != nil { | |
return option.Value | |
} | |
return defaultValue | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment