Golang默认参数和可变参数
Golang函数支持默认参数吗?No
Golang函数支持可变参数吗?Yes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import "fmt"
//可变参数的声明
func test(a ...int) {
var total int
for _, num := range(a) {
total += num
}
fmt.Println(total)
}
func main() {
params := []int{1,2,3,4}
//可变参数传参方式
test(params...)
test(2,3,4,5)
}
//结果
10
14
Ok,可变参数的问题解决了,那默认参数怎么解决呢?直接说思路:
既然Golang不支持默认参数,那就在函数内部构造默认参数,通过读取可变参数来修改默认参数.代码大概会这样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 函数的参数聚合struct
type Params struct {
Allow bool
Size int
}
func defaultParamsTest(optionalParams ...interface{}) {
// 声明默认的参数
p := Params{
Allow: true,
Size: 100,
}
// 根据传参optionalParams修改p
}
这样会有个问题,你的optionalParams虽然可以是interface{}类型,但是并不能很好的从传参中读懂要设置什么值. 于是我们需要改造一下optionalParams这个参数. 它需要做到两点:
- 可变长的传参
- 能够修改p的值
第一点很简单,通过Go的...
语法可以实现
第二点则需要理解函数在Go中也跟Python类似,是可以作为传参的”一等公民”。因此可以通过传递一个函数参数,接收p的指针作为,达到修改p的目的。代码可能会是这样:
1
2
3
4
5
6
7
8
9
10
11
func defaultParamsTest(optionalParams ...func(p *Params, v interface{})) {
// 声明默认的参数
p := Params{
Allow: true,
Size: 100,
}
// 根据传参optionalParams修改p
for _, f := range(optionalParams) {
f()
}
}
这样写会遇到的问题是optionalParams函数中的v值读取不到.怎么办呢?*Params是函数内部可以获取的,v参数如何传递呢.动态构建固定参数的函数是一种方法
1
2
3
4
5
6
// WithAllow返回的函数,接受一个*Params参数,并把Allow的bool传参设置到*Params中
func WithAllow(b bool) func(p *Params){
return func(p *Params){
p.Allow = b
}
}
完整的例子
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
45
package main
import "fmt"
// 构造一个参数结构
type Params struct {
Allow bool
Size int
}
func defaultParamsTest(optionalParams ...func(p *Params)) {
// 声明默认的参数
p := Params{
Allow: true,
Size: 100,
}
// 根据传参optionalParams修改p
for _, f := range optionalParams {
f(&p)
}
fmt.Printf("%+v", p)
}
func WithAllow(b bool) func(p *Params) {
return func(p *Params) {
p.Allow = b
}
}
func WithSize(v int) func(p *Params) {
return func(p *Params) {
p.Size = v
}
}
func main() {
params := []func(p *Params){
WithAllow(false),
WithSize(50),
}
defaultParamsTest(params...)
}
//打印结果
{Allow:false Size:50}
总结
- 将可变的参数聚合到一个struct中
- 函数内部声明这个struct
- 声明一个类似WithAllow的函数,将可变参数的设置通过函数的方式提供给用户设置
优点
- 对用户友好,可以很方便的拓展和修改可变参数。
缺点
- 代码量增加了
这就是grpc-go项目中使用到的思路。但是grpc-go对函数传参和WithAllow的返回结果在作了一层抽象,但是整体思路一样。
Reference
dialoptions.go文件和clientconn.go文件分别有设计和使用