Optional Design Pattern is everywhere in each Open-Source Go Project — gRPC / Opentelemetry
When I was doing projects on gRPC and opentelemetry, both projects are in Go Lang. I see the configuration setup is done in different way which create a curiosity inside me to look into the implementation of the design pattern which is used behind the configuration setup. This design pattern is optional design pattern also known as functional design pattern. I have created a full length video too on the same design pattern: Optional / Functional Design Pattern Go Lang | Used In OpenSource Projects gRPC & Opentelemetry — YouTube

Understanding Functional Options
Functional Options is a design pattern commonly used in Go to create objects with customizable configurations. It leverages the power of first-class functions to allow users to specify various options during object initialization.
Implementation Overview
We’ll create a simplified package manager that allows users to define package attributes such as name, version, description, and dependencies using Functional Options. Here’s an overview of our implementation:
- Define a
Package
struct representing a software package. - Implement
PackageOption
as a functional type for modifying package configuration. - Define functions like
WithVersion
,WithDescription
, andWithDependencies
as Functional Options to set different attributes of the package. - Implement
NewPackage
function to create a new package with the provided options.
Code Implementation
// Package represents a software package
type Package struct {
Name string
Version string
Description string
Dependencies []string
}
// PackageOption represents a function that modifies Package configuration
type PackageOption func(*Package)
// WithVersion sets the package version
func WithVersion(version string) PackageOption {
return func(p *Package) {
p.Version = version
}
}
// WithDescription sets the package description
func WithDescription(description string) PackageOption {
return func(p *Package) {
p.Description = description
}
}
// WithDependencies sets the package dependencies
func WithDependencies(dependencies ...string) PackageOption {
return func(p *Package) {
p.Dependencies = dependencies
}
}
// NewPackage creates a new Package with the provided options
func NewPackage(name string, options ...PackageOption) *Package {
pkg := &Package{
Name: name,
}
for _, option := range options {
option(pkg)
}
return pkg
}
Usage Example
func main() {
// Create a new package with custom options
pkg := NewPackage(
"example-package",
WithVersion("1.0.0"),
WithDescription("This is an example package."),
WithDependencies("dependency1", "dependency2"),
)
// Print package information
fmt.Println("Package Name:", pkg.Name)
fmt.Println("Package Version:", pkg.Version)
fmt.Println("Package Description:", pkg.Description)
fmt.Println("Package Dependencies:", pkg.Dependencies)
}
Functional Options pattern empowers developers to build configurable components in a clean and concise manner, making it a valuable tool in Go programming.