小能豆

Golang 中 WithOptions 模式的组合

go

在 golang 中,可变参数选项有一个非常酷的模式:

CallSomeStaff(mandatoryArg, WithSomeVariadicOption(val1), WithOtherVariadicOption(val2))

但是,一旦我们想要使用任何可能添加自己的可变参数选项的超级函数来扩展逻辑,最佳/预期的实践(或至少是适当的解决方案)是什么。

这似乎很棘手

  • 选项本身的类型并不总是公开的,只是选项修饰符
  • 我不太确定,但我对此很感兴趣。是一种事件类型的选项修饰符的情况,其中私有而不是仅公开最终的修饰符函数值

那么是否真的可以顺利实施类似的事情

func SupperWrapper(composedOptions ...SuperOrInheritedOptions) {
   superOptions := // filter for SuperOptions
   inheritedOptions := // filter for InheritedOptions

   doWhateverWith(superOptions)

   CallSomeWrappedStaff(...inheritedOptions)
}

interface{}作为一种期权类型的方法看起来太诡异了。

我能看到的最漂亮的可以实现的东西看起来像

SuperStaff(
  WithSupperOption1(), 
  WithSuperOption2(), 
  WithInheritedOptions(
    WithInheritedOption1(), 
    WithInheritedOption2(),
 ),
)

无论如何,有可能真的最终得到简单的选项组合,如

SuperStaff(
  WithSupperOption1(), 
  WithSuperOption2(), 
  WithInheritedOption1(), 
  WithInheritedOption2(),
)

超级问题是,一旦原始类型没有暴露其本身的选项,甚至修饰符类型,真正的选项是什么。

PS 据我了解(作为最简单的解决方案)类型组合如

type CompositeOptions = SuperOptions | InheritedOptions

golang 不支持。不是吗?


阅读 35

收藏
2023-11-04

共1个答案

小能豆

在 Go 中,要实现可变参数选项模式,你可以使用函数选项模式,它是一种常见的设计模式。这种模式允许你以清晰和可扩展的方式为函数传递配置选项。

首先,你需要定义一个函数类型,通常命名为 Option,它接受一个指向某个配置对象的指针,并返回错误。然后,你可以定义函数选项,这些函数选项实际上是函数,它们可以操作配置对象。最后,你的函数接受可变数量的函数选项作为参数。

下面是一个示例,演示了如何实现可变参数选项模式:

package main

import (
    "fmt"
)

type Config struct {
    Option1 string
    Option2 int
}

type Option func(*Config) error

func WithOption1(value string) Option {
    return func(c *Config) error {
        c.Option1 = value
        return nil
    }
}

func WithOption2(value int) Option {
    return func(c *Config) error {
        c.Option2 = value
        return nil
    }
}

func SuperFunction(config *Config, options ...Option) {
    for _, opt := range options {
        if err := opt(config); err != nil {
            fmt.Printf("Error applying option: %v\n", err)
        }
    }
    // Your super function logic using the config.
    fmt.Printf("Option1: %s, Option2: %d\n", config.Option1, config.Option2)
}

func main() {
    config := &Config{}

    // Call SuperFunction with options.
    SuperFunction(config, WithOption1("Value1"), WithOption2(42))
}

在这个示例中,Option 是一个函数类型,每个函数选项(如 WithOption1WithOption2)都返回一个满足 Option 函数签名的函数。SuperFunction 接受一个配置对象以及任意数量的函数选项,它依次应用这些选项来配置对象。最后,你可以在 SuperFunction 中执行你的逻辑,使用配置对象中的配置选项。

这种模式允许你轻松地扩展配置选项,而不需要修改函数的签名,同时保持了清晰和可读性。这是 Go 中常用的一种模式,用于构建可配置的函数和方法。

2023-11-04