在Go语言中,有一种传递选项给函数的规范方式吗?

huangapple go评论82阅读模式
英文:

Is there a canonical way of passing options to a Go function?

问题

我正在编写一个暴露这个函数的包:

func Marshal(input interface{}) ([]byte, error)

对于大多数情况来说,这是可以的,但如果有额外的选项,我还想提供另一个函数:

type MarshalOptions struct {
    OnlyStdClass bool
}

func MarshalWithOptions(input interface{}, options MarshalOptions) ([]byte, error)

这样做是推荐的方式吗?是否有一种标准的命名约定,用于提供带有选项的更具体版本的函数?

英文:

I am writing a package that exposes this function:

func Marshal(input interface{}) ([]byte, error)

This is fine for the majority of situations, but I also want to prove another function if there are extra options:

type MarshalOptions struct {
    OnlyStdClass bool
}

My first thought is to create another function:

func MarshalWithOptions(input interface{}, options MarshalOptions) ([]byte, error)

Is this the recommended way of doing this? Is there a standard naming convention for function that also provide a more specific version with options?

答案1

得分: 1

一种常见的方法是将函数声明为可变参数函数,以便它接受零个或多个选项。假设Option是你的选项类型,你可以这样声明它:

func Marshal(input interface{}, options ...Option) ([]byte, error)

然后,在函数内部,options的类型是[]Option

函数可以使用零个或多个Option参数进行调用:

bytes, err := Marshal(input, Option1, Option2)

或者,如果你的选项在一个切片中,你可以这样调用它:

bytes, err := Marshal(input, options...)

语言规范中有几个关于这个的参考(搜索"variadic")。

英文:

One common way of doing that is to declare the function as variadic so that it accepts zero or more options. Assuming Option is your option type, you would declare it like this:

func Marshal(input interface{}, options ...Option) ([]byte, error)

Then, within the function, options has the type []Option.

The function would then be called with zero or more Option arguments:

bytes, err := Marshal(input, Option1, Option2)

Or, if you have your options in a slice, you would call it like this:

bytes, err := Marshal(input, options...)

There are several references to this in the language spec (look for "variadic").

答案2

得分: 0

你可以使用*MarshalOptions。调用者可以传入nil,以使用默认行为。

例如:
func Marshal(input interface{}, options *MarshalOptions) ([]byte, error)

英文:

You can take a *MarshalOptions. The caller can then pass nil if they want the default behavior.

eg.
func Marshal(input interface{}, options *MarshalOptions) ([]byte, error)

答案3

得分: 0

我发现这是明确和简洁之间的最佳平衡:

type MarshalOptions struct {
    OnlyStdClass bool
}

// DefaultMarshalOptions将创建一个带有合理默认值的MarshalOptions实例。有关选项的完整描述,请参见MarshalOptions。
func DefaultMarshalOptions() *MarshalOptions {
    options := new(MarshalOptions)
    options.OnlyStdClass = false

    return options
}

func Marshal(input interface{}, options *MarshalOptions) ([]byte, error) {
    // ...
}

使用构造函数模式,我可以设置合理的默认值,而不需要显式设置每个选项(特别是如果它们可能会更改)。

虽然我可以接受nil,但我不这样做,因为这样更明确易读:

result := Marshal(123, DefaultMarshalOptions())
英文:

I found this to the be the best balance between explicit and simplicity:

type MarshalOptions struct {
    OnlyStdClass bool
}

// DefaultMarshalOptions will create a new instance of MarshalOptions with
// sensible defaults. See MarshalOptions for a full description of options.
func DefaultMarshalOptions() *MarshalOptions {
    options := new(MarshalOptions)
    options.OnlyStdClass = false

    return options
}

func Marshal(input interface{}, options *MarshalOptions) ([]byte, error) {
    // ...
}

Using the constructor pattern I can set reasonable defaults, without requiring that every option (especially if they may change) are explicitly set.

It's true that I could accept nil, but I don't because it makes it more explicit to read:

result := Marshal(123, DefaultMarshalOptions())

huangapple
  • 本文由 发表于 2017年3月14日 10:45:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/42776885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定