golang-struct-option-value

Golang中初始化struct之后如何优雅的设置一些字段的值.现在来学习下k8s源码中是如何做的

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main

import "fmt"

type Config struct {
a int
b int
res resource
}

type resource struct {
kind string
}

// Option接口
type Option interface {
Apply(*Config)
}

type aOption int

// 为需要修改的字段实现一个Apply方法,具体修改struct中的字段内容
func (o aOption) Apply(config *Config) {
config.a = int(o)
}

// 返回aOption类型的值
func WithA(a int) Option {
return aOption(a)
}

type resourceOption struct {
res resource
}

func (o resourceOption) Apply(config *Config) {
config.res = o.res
}

func WithRes(res resource) Option{
return resourceOption{res: res}
}



// newA opts为可选参数
func newA(opts ...Option) *Config {
config := &Config{
a: 0,
b: 0,
res: resource{
kind: "Cat",
},
}
// 执行额外的赋值操作,通过opts中的内容修改config中的值
for _, opt := range opts{
opt.Apply(config)
}
return config
}


func main() {
opts := []Option{WithA(1), WithRes(resource{kind: "Dog"})}
r := newA(opts...)
fmt.Println(r) // &{1 0 {Dog}}

}

另外一种类似的方法,相当于省略了Apply函数,将Apply函数的内容写在了WithClientSet函数中。

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
package main

import "fmt"

type frameworkOptions struct {
clientSet string
}

type fOption func(*frameworkOptions)

func WithClientSet(clientSet string) fOption {
return func(o *frameworkOptions) {
o.clientSet = clientSet
}
}

func newFrameWork(opts ...fOption) *frameworkOptions {
fr := &frameworkOptions{
clientSet: "Cat",
}
// 执行额外的赋值操作,通过opts中的内容修改frameworkOptions中的值
for _,opt := range opts {
opt(fr)
}
return fr
}


func main() {
opts := []fOption{WithClientSet("Dog")}
r := newFrameWork(options...)
fmt.Println(r) // &{Dog}
}


REF:
1.https://github.com/kubernetes/kubernetes/blob/master/vendor/go.opentelemetry.io/otel/sdk/metric/controller/basic/config.go