引
昨天晚上快速看了 uber go 风格指南,发现最后一条技巧,对 API 设计有帮助,拿出来大家一起讨论下。
回顾
bad code
// package db
func Connect(
addr string,
timeout time.Duration,
caching bool,
) (*Connection, error) {
// ...
}
// Timeout and caching must always be provided,
// even if the user wants to use the default.
db.Connect(addr, db.DefaultTimeout, db.DefaultCaching)
db.Connect(addr, newTimeout, db.DefaultCaching)
db.Connect(addr, db.DefaultTimeout, false /* caching */)
db.Connect(addr, newTimeout, false /* caching */)
good code
type options struct {
timeout time.Duration
caching bool
}
// Option overrides behavior of Connect.
type Option interface {
apply(*options)
}
type optionFunc func(*options)
func (f optionFunc) apply(o *options) {
f(o)
}
func WithTimeout(t time.Duration) Option {
return optionFunc(func(o *options) {
o.timeout = t
})
}
func WithCaching(cache bool) Option {
return optionFunc(func(o *options) {
o.caching = cache
})
}
// Connect creates a connection.
func Connect(
addr string,
opts ...Option,
) (*Connection, error) {
options := options{
timeout: defaultTimeout,
caching: defaultCaching,
}
for _, o := range opts {
o.apply(&options)
}
// ...
}
// Options must be provided only if needed.
db.Connect(addr)
db.Connect(addr, db.WithTimeout(newTimeout))
db.Connect(addr, db.WithCaching(false))
db.Connect(
addr,
db.WithCaching(false),
db.WithTimeout(newTimeout),
)
技巧肢解
里面主要用了两种技巧
- 可变长参数
- 函数(或者接口)当配置
可变长参数的好处
gout https://github.com/guonaihong/gout
gout(流式 http client) 可以使用 SetCookies 可以设置一个或者多个 cookie。在大多数开源库里面用了两个函数实现类似功能。gout 这里用上可变长参数可以减少 API 个数。
gin 里面
在 gin(API 框架) Run 函数就是可变长参数经典用法,你可以用 router.Run()起个默认服务,也可以用 router.Run(":1234") 指定端口起服务。这里也可以减少 API 个数,写起来很爽。
上面举的例子可以归纳出,可变长参数用在,函数参数个数 >=0 的地方,很爽。
函数(接口)当配置
//TODO,中午再补上。