• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Option Pattern in Go: Advanced Parameter Handling

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



In Go, the Option pattern (also known as the configuration pattern or constructor pattern) is a commonly used design pattern, primarily for handling function parameters, especially when a function has many optional parameters. By using the Option pattern, we can pass and configure function parameters in a flexible and extensible way, avoiding the maintenance challenges and complexity of traditional methods with too many parameters.

Let’s take a look at how the Option pattern is used in Go, analyze its implementation principles, and help you better understand how to apply this pattern in real-world projects.

Why Do We Need the Option Pattern?


When constructing complex objects in Go, we often encounter the following pain points:

Drawbacks of Traditional Constructors


// Example problem: Parameter explosion and difficult maintenance
func NewServer(addr string, port int, timeout time.Duration, maxConn int, protocol string) *Server {
// ...
}

Pain point analysis:

  • The order of parameters is sensitive
  • Cannot set default values
  • Adding parameters requires modifying all callers
  • Poor readability (hard to distinguish whether 0 is a valid value or a default)

So, how can we solve or avoid these problems?

Core Concept of the Option Pattern


The core of the Option pattern is to set the configuration of an object or function through optional function parameters, instead of putting all the configuration items in the function’s parameter list. These functions are usually called “Options”, and by combining multiple options, you can complete complex configurations.

By using function closures and variadic parameters, you can flexibly configure objects:

Constructor -> Accepts a list of Option functions -> Applies default configuration -> Iterates and executes Option functions -> Returns the fully configured object

Basic Implementation Approach


Let’s illustrate how to use the Option pattern to simplify configuration and parameter passing by creating a server client.

Define a Configuration Struct


type Server struct {
addr string
port int
timeout time.Duration
maxConn int
protocol string
}

type Option func(*Server)
Implement Option Functions


func WithTimeout(t time.Duration) Option {
return func(s *Server) {
s.timeout = t
}
}

func WithMaxConn(max int) Option {
return func(s *Server) {
s.maxConn = max
}
}
Implement the Constructor Function


func NewServer(addr string, opts ...Option) *Server {
s := &Server{
addr: addr,
port: 8080, // default port
timeout: 30 * time.Second,
maxConn: 100,
protocol: "tcp",
}

for _, opt := range opts {
opt(s) // apply all Option functions
}
return s
}
Usage Example


server := NewServer("localhost",
WithTimeout(60*time.Second),
WithMaxConn(500),
)
Advanced Optimization Techniques

Configuration Validation


// If the port is less than 0 or greater than 65535, show an error
func WithPort(port int) Option {
return func(s *Server) {
if port < 0 || port > 65535 {
panic("invalid port number")
}
s.port = port
}
}
Grouped Configuration


type NetworkOptions struct {
Protocol string
Timeout time.Duration
}

func WithNetworkOptions(opts NetworkOptions) Option {
return func(s *Server) {
s.protocol = opts.Protocol
s.timeout = opts.Timeout
}
}

// Using grouped configuration
server := NewServer("localhost",
WithNetworkOptions(NetworkOptions{
Protocol: "udp",
Timeout: 10*time.Second,
}),
)
Comparison with Traditional Patterns


Initialization scenario:

  • Traditional pattern: Parameter list is lengthy and redundant
  • Option pattern: Chain-style invocation is clear and readable

Modifying parameters scenario:

  • Traditional pattern: All calling places need to be updated
  • Option pattern: Adding a new Option does not affect existing code
Application Scenarios and Best Practices


Applicable scenarios:

  • When there are more than 3 configuration parameters
  • When default values need to be supported
  • When parameters are interdependent
  • When configuration items need to be extended dynamically

Best practices:

  • Naming convention: Option functions should start with the prefix With
  • Parameter validation: Complete parameter checking within Option functions
  • Documentation: Clearly specify the scope and default value of each Option
  • Performance-sensitive scenarios: Reuse Option objects

var HighPerfOption = WithMaxConn(1000)

func CreateHighPerfServer() *Server {
return NewServer("localhost", HighPerfOption)
}
Comparison with Other Patterns


Option Pattern:

  • Advantages: Flexible, good readability
  • Disadvantages: Closures introduce slight performance overhead
  • Suitable scenarios: Construction of complex objects

Builder Pattern:

  • Advantages: Step-by-step construction
  • Disadvantages: Requires maintenance of a Builder class
  • Suitable scenarios: Complex object construction processes

Function Parameters:

  • Advantages: Simple implementation
  • Disadvantages: Difficult to extend
  • Suitable scenarios: Simple scenarios with fewer than 3 parameters
Complete Example Code


package main

import (
"fmt"
"time"
)

type Server struct {
addr string
port int
timeout time.Duration
maxConn int
protocol string
}

type Option func(*Server)

func WithPort(port int) Option {
return func(s *Server) {
if port < 0 || port > 65535 {
panic("invalid port number")
}
s.port = port
}
}

func WithTimeout(timeout time.Duration) Option {
return func(s *Server) {
s.timeout = timeout
}
}

func WithMaxConn(maxConn int) Option {
return func(s *Server) {
s.maxConn = maxConn
}
}

func WithProtocol(protocol string) Option {
return func(s *Server) {
s.protocol = protocol
}
}

func NewServer(addr string, opts ...Option) *Server {
s := &Server{
addr: addr,
port: 8080,
timeout: 30 * time.Second,
maxConn: 100,
protocol: "tcp",
}

for _, opt := range opts {
opt(s)
}
return s
}

func main() {
server := NewServer("localhost",
WithPort(9090),
WithTimeout(60*time.Second),
WithMaxConn(500),
WithProtocol("udp"),
)

fmt.Printf("%+v\n", server)
}

Output:


&{addr:localhost port:9090 timeout:1m0s maxConn:500 protocol:udp}
Summary


Core advantages of the Option pattern:

  • Readability: Each configuration item’s function is clear
  • Extensibility: Adding new parameters does not affect existing code
  • Safety: Built-in parameter validation capability
  • Flexibility: Supports dynamic combination of configuration items

Recommendations:

  • For small projects or simple object construction, do not over-engineer
  • Strongly recommended for public libraries or complex configurations
  • Combining interfaces and type aliases can create more powerful DSLs

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.





Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:

Multi-Language Support

  • Develop with Node.js, Python, Go, or Rust.

Deploy unlimited projects for free

  • pay only for usage — no requests, no charges.

Unbeatable Cost Efficiency

  • Pay-as-you-go with no idle charges.
  • Example: $25 supports 6.94M requests at a 60ms average response time.

Streamlined Developer Experience

  • Intuitive UI for effortless setup.
  • Fully automated CI/CD pipelines and GitOps integration.
  • Real-time metrics and logging for actionable insights.

Effortless Scalability and High Performance

  • Auto-scaling to handle high concurrency with ease.
  • Zero operational overhead — just focus on building.

Explore more in the

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

!


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Follow us on X:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.




Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.




Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу