【Golang】Functional Options编程第二弹

108 阅读2分钟

前言

可以先看看【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编程模式扩展性很强,可以灵活运用