Golang函数选项:是否应该返回err来处理错误?

Golang函数选项:是否应该返回err来处理错误? 我发现了这个包含Go模式的Git仓库:

github.com

函数式选项

函数式选项是在Go中实现清晰/优雅API的一种方法。 作为函数实现的选项会设置该选项的状态。

实现

选项

package file

type Options struct {
	UID         int
	GID         int
	Flags       int
	Contents    string
	Permissions os.FileMode
}

此文件已被截断。显示原文

例如,以下代码不允许在评估给定参数时产生错误:

func UID(userID int) Option {
	return func(args *Options) {
		args.UID = userID
	}
}

如果选项被定义成这样,会不会更好?

type Option func(*Options) error

更多关于Golang函数选项:是否应该返回err来处理错误?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好 @guettli

理论上,设置一个选项应该足够简单,以至于不会出错。如果出于某种原因需要事先计算该选项,并且这种计算可能导致错误,这可以在调用选项函数之前完成。

更多关于Golang函数选项:是否应该返回err来处理错误?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在函数选项模式中,是否返回 error 取决于选项验证的复杂性和必要性。以下是两种实现方式的对比:

1. 不返回 error 的简单选项(适合无验证场景)

type Option func(*Options)

func UID(userID int) Option {
    return func(opts *Options) {
        opts.UID = userID
    }
}

// 使用示例
func NewFile(opts ...Option) (*File, error) {
    options := &Options{UID: 1000} // 默认值
    for _, opt := range opts {
        opt(options)
    }
    return createFile(options)
}

2. 返回 error 的验证选项(需要参数验证时)

type Option func(*Options) error

func UID(userID int) Option {
    return func(opts *Options) error {
        if userID < 0 {
            return fmt.Errorf("invalid UID: %d", userID)
        }
        opts.UID = userID
        return nil
    }
}

// 使用示例
func NewFile(opts ...Option) (*File, error) {
    options := &Options{UID: 1000}
    for _, opt := range opts {
        if err := opt(options); err != nil {
            return nil, err
        }
    }
    return createFile(options)
}

3. 混合方案:延迟验证

type Option func(*Options)

func ValidUID(userID int) Option {
    return func(opts *Options) {
        opts.UID = userID
        opts.validateUID = true
    }
}

func NewFile(opts ...Option) (*File, error) {
    options := &Options{}
    for _, opt := range opts {
        opt(options)
    }
    
    // 集中验证
    if options.validateUID && options.UID < 0 {
        return nil, fmt.Errorf("invalid UID: %d", options.UID)
    }
    
    return createFile(options)
}

选择建议:

  • 如果选项需要立即验证(如无效参数会导致后续操作失败),使用返回 error 的方案
  • 如果验证可以延迟或选项很简单,使用不返回 error 的方案更简洁
  • 复杂场景可考虑在构造函数中统一验证

实际案例:标准库 http.ListenAndServehttp.Server 配置就使用了函数选项模式,选项函数不返回错误,验证在服务器启动时进行。

回到顶部