函数的不定参
新亮笔记、gRPC、kratos、progressbar 等项目都大量用到了这个写法。
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
| type Logger struct {
// ...
}
type Option func(*option)
type option struct {
level Level
fields map[string]string
file io.Writer
timeLayout string
disableConsole bool
}
func NewLogger(opts ...Option) (*Logger, error) {
logger := new(option)
for _, f := range opts {
f(opt)
}
// ...
logger := XXX
return logger, nil
}
func WithErrorLevel() Option {
return func(opt *option) {
opt.level = ErrorLevel
}
}
func WithField(key, value string) Option {
return func(opt *option) {
opt.fields[key] = value
}
}
|
使用
1
2
3
| logger, err := NewLogger(
WithField("key", "value"),
)
|
这样写有一个好处,后续新增其他参数时,也很方便配置。
接口相关
1
2
3
4
5
6
7
8
9
10
| var _ Student = (*student)(nil) // 一
type Student interface {
i() // 二
Study()
}
type student struct {
Name string
}
|
第一种
1
| var _ Student = (*student)(nil)
|
强制 *student
去实现 Student
接口,编译器会进行检查。
如果没有实现呢,编译器就会报错:
panic: runtime error: invalid memory address or nil pointer dereference
如果去掉那一行强制检查,就不会报错了。
第二种
这也是一种很巧妙的写法,强制 Student
接口中的方法只能在本包中实现,因为有这个首字母小写的方法,其他包是不能实现的。这里的方法名只要是首字母小写就可以。