查看原文
其他

Go语言常见错误 | 不使用function option模式

云原生Go 源自开发者
2024-08-28

在使用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 代码。


文章精选

Go语言常见错误| 意外的变量隐藏

Go语言常见错误| 不必要的代码嵌套

Go语言常见错误| 误用init函数

Go语言常见错误| 滥用getters/setters

Go语言常见错误 | 接口污染

Go语言常见错误| 将接口定义在实现方一侧


点击关注并扫码添加进交流群领取「Go 语言」学习资料

继续滑动看下一个
源自开发者
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存