前言
可以先看看【Golang】编程模式:Functional Options
Functional Options编程demo第二弹
代码示例:
// doSomething 做某些事...
// param1和param2是方法的固定参数
// options是方法的可选参数,为方法带来了扩展能力,当doSomething方法又需要其他参数时,可以无需修改方法签名(即无需修改接口、无需修改协议),只需要新增一个Option即可,避免了修改所有调用方,避免了牵一发动全身的问题
func doSomething(param1 string, param2 string, options ...DoSomethingOption) {
fmt.Printf("do something with param1, %s\n", param1)
fmt.Printf("do something with param2, %s\n", param2)
// 合并所有option
option := MergeDoSomethingOption(options...)
if len(option.Resource1) != 0 {
fmt.Printf("do something with Resource1, %s\n", option.Resource1)
}
if option.Tag1 {
fmt.Printf("do something when Tag1 is true")
}
}
type DoSomethingOption struct {
Resource1 string
Tag1 bool
}
// WithResource1Option 创建Resource1 Option
func WithResource1Option(resource1 string) DoSomethingOption {
return DoSomethingOption{
Resource1: resource1,
}
}
// WithTag1Option 创建Tag1 Option
func WithTag1Option(tag1 bool) DoSomethingOption {
return DoSomethingOption{
Tag1: tag1,
}
}
// MergeDoSomethingOption 合并多个Option
func MergeDoSomethingOption(options ...DoSomethingOption) DoSomethingOption {
res := DoSomethingOption{}
for _, option := range options {
if len(option.Resource1) != 0 {
res.Resource1 = option.Resource1
}
res.Tag1 = option.Tag1
}
return res
}
func main() {
doSomething("1", "2")
fmt.Println("------------------")
doSomething("A", "B", WithResource1Option("Resource1"))
fmt.Println("------------------")
doSomething("param1", "param2", WithResource1Option("Resource1"), WithTag1Option(true))
}
运行结果如下:
do something with param1, 1
do something with param2, 2
------------------
do something with param1, A
do something with param2, B
do something with Resource1, Resource1
------------------
do something with param1, param1
do something with param2, param2
do something with Resource1, Resource1
do something when Tag1 is true
分析
【若不使用Functional Options编程】:
doSomething方法每次需要一个新参数时,都要修改方法签名,即修改接口、修改协议,带来的问题是所有调用方都要修改,会导致牵一发而动全身,很痛苦。
【若使用Functional Options编程】:
doSomething方法每次需要一个新参数时,只需要往Option struct中新增参数,然后新增一个Option,调用方法时传递新Option即可,不需要修改方法签名,就不会有牵一发动全身的问题了。
总结
其实通过两篇文章可以看出Functional Options编程模式扩展性很强,可以灵活运用。