Go语言常见错误 | 不使用function option模式
在使用Golang进行复杂的开发任务时,处理一个结构体有许多可选的配置项是常有的事。这也是在许多函数设计中共有的特征,因为这使得函数更容易使用,灵活性更强。然而,有时我们可能会看到错误的实践,那就是“遗漏使用 Function Option
模式”。在这篇文章中,我将详细解释Function Option
的概念,并指出为什么我们应该使用它。我还将给出实例来展示如果忽略了Function Option
,可能会出现哪些问题。
Function Option 的基本概念
在 Go 语言中,Function Option
是一种用于设计准备接受许多设置项的结构体的技术。在没有 Function Option
的情况下,我们通常返回结构体的指针,并通过函数设置可选项。下面是一个无Function Option
的示例:
type Config struct {
A string
B int
}
func NewConfig() *Config {
return &Config {
A: "default A",
B: 0,
}
}
func main() {
cfg := NewConfig()
cfg.A = "non-default A"
cfg.B = 1
}
遗漏使用 Function Option 的问题
上述代码的问题在于,如果 Config 结构体有许多设置项,我们就必须设置每一项,即使我们只关心某几项。此外,散乱的设置代码可能混入我们的业务代码中,导致代码变得难以阅读和维护。
对于使用默认选项的情况,我们得到的是一个部分初始化的结构体,我们可能忘记设置重要的选项,引入bug。另一个问题是,如果添加新的设置项,我们需要在代码中找到每个实例并更新它们,这会很麻烦。
应用Function Option模式
如果我们使用函数选项模式,上述代码将被优化为:
type Config struct {
A string
B int
}
type Option func (*Config)
func WithA(a string) Option {
return func(c *Config) {
c.A = a
}
}
func WithB(b int) Option {
return func(c *Config) {
c.B = b
}
}
func NewConfig(opts ...Option) *Config {
config := &Config{
A: "default A",
B: 0,
}
for _, opt := range opts {
opt(config)
}
return config
}
func main() {
cfg := NewConfig(
WithA("non-default A"),
WithB(1),
)
}
这里,WithA()
和WithB()
函数返回的是改变Config
的函数,而NewConfig()
接受这些函数作为参数。这样做带来了以下优点:
提高了代码的可读性,我们可以清楚地看到我们正在改变哪些选项。 我们可以轻松地添加新的设置项,而无需在代码中查找并更改每个实例。 我们避免了部分初始化的问题,因为 NewConfig()
默认设置好了所有选项。
结语
忽略 Function Option
模式可能会导致代码混乱,增加代码维护的难度,并可能引入错误。在设计接受许多设置项的函数或类型时,使用 Function Option
模式是一种非常好的做法。我希望本文可以帮助大家更好地理解和使用这种模式,并写出更优雅、可读性更强的 Go 代码。