阅读uber内部关于实践多年的golang编码规范,看到关于Function options的一条:
关于 functional options 简单来说就是通过类似闭包的方式来进行函数传参
不提倡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 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 */)// package db
|
提倡:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
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),
)
|
golang对世界的抽象原语
联想到了c++和 go抽象方式的对比:
程序语言作为人与计算机之间的翻译官,需要完成对现实世界的抽象表达,然后转换为计算机理解的二进制指令,并执行。在二进制里完成现实世界的计算任务。更优雅的抽象能力,让程序语言表达能力更强,提升编码的效率。
- struct => 有由xxxx构成的东西
- interface => 会xxxx的东西
- 匿名 =>东西的组装组合
- 函数 => 谓词 :将xxxx处理成xxxx
- 闭包 =>能够将xxxx处理成xxxx的东西(函数对象)
c++提供了函数重载和默认函数等方式来实现这种方式的可变参数调用,但是golang没有提供函数重载的能力
如何理解下面的这个函数:
1
2
3
4
5
6
7
8
9
10
11
12
|
func Connect(addr string, opts ...Option,) (*Connection, error)
// Option => 一种会处理apply 选项的东西
type Option interface {
apply(*options)
}
// 输入: 一个时间,输出:一个具有"将Options的超时时间设置为输入时间"能力的东西
func WithTimeout(t time.Duration) Option
|
参考: