考虑这个结构:
type Intervals struct {
DefaultDuration time.Duration
FailDuration time.Duration
}
我们还假设持续时间列表将来可能会扩展。
它用于一个简单的 CRUD API,可让您更改这些持续时间(如
SetDefaultDuration
)。因此,我们希望验证设置请求中的值,并设置一些默认值。但是,如果我们想使用一些外部配置来配置验证,并以相同的方式配置默认值,该怎么办?例如:
DefaultDuration
应大于1s,无默认值FailDuration
应介于 5 秒到 30 秒之间,默认值为 15 秒那么,问题是 - 在 Go 中哪些方法适合解决这个问题?
似乎为每个持续时间类型(以及类型本身)定义工厂应该可行,但我认为太冗长了。这是例子:
type FailDuration time.Duration
type FailDurationFactory struct {
defaultValue time.Duration
minValue time.Duration
}
func NewFactory(cfg Config) (FailDurationFactory, error) {
// build from the cfg
}
func (f FailDurationFactory) New(d time.Duration) (FailDuration, error) {
// set default & validate & return
}
Config
可以从文件加载,例如,在应用程序启动时从 JSON 解组。
这看起来像是功能选项的用例。
按照 Uber Go 风格指南的风格实现,可能看起来像这样(Go Playground):
package main
import (
"fmt"
"time"
)
type intervals struct {
defaultDuration time.Duration
failDuration time.Duration
}
type Interval interface {
apply(*intervals)
}
type defaultDuration time.Duration
func (d defaultDuration) apply(i *intervals) {
i.defaultDuration = time.Duration(d)
}
func WithDefaultDuration(d time.Duration) Interval {
return defaultDuration(d)
}
type failDuration time.Duration
func (f failDuration) apply(i *intervals) {
i.failDuration = time.Duration(f)
}
func WithFailDuration(d time.Duration) Interval {
return failDuration(d)
}
const DefaultFailDuration = 5 * time.Second
func DoSomething(
ivs ...Interval,
) {
iv := intervals{
failDuration: DefaultFailDuration,
}
for _, i := range ivs {
i.apply(&iv)
}
fmt.Printf("%#v\n", iv)
}
func main() {
DoSomething()
DoSomething(WithDefaultDuration(100 * time.Millisecond))
DoSomething(WithDefaultDuration(100*time.Millisecond), WithFailDuration(15*time.Second))
}
当然,您可以根据您的用例调整样式。