go中常用的两种设计模式(函数选项模式)

46 阅读1分钟
  1. 函数选项模式
type Server struct {
   Addr         string
   Port         string
   ReadTimeOut  time.Duration
   WriteTimeOut time.Duration
   TimeOut      time.Duration
}

func NewServer(addr, port string, readTimeOut, writeTimeOut, timeOut time.Duration) Server {
   return Server{
      Addr:         addr,
      Port:         port,
      ReadTimeOut:  readTimeOut,
      WriteTimeOut: writeTimeOut,
      TimeOut:      timeOut,
   }
}

func main() {
   server := NewServer("", "", 10*time.Second, 10*time.Second, 20*time.Second)
   fmt.Println(server)
}

如上,是我们经常遇到的代码,如果我要初始化一个server对象,那么必须传入所有的addr,port等参数,如果我期望的是某个参数为空,使用默认值,这种方式是达不到的。为此,我们使用一种设计模式,或者是实现方法来解决这个问题。

type Server struct {
   Addr         string
   Port         string
   ReadTimeOut  time.Duration
   WriteTimeOut time.Duration
   TimeOut      time.Duration
}

func NewServer(addr, port string, readTimeOut, writeTimeOut, timeOut time.Duration) Server {
   return Server{
      Addr:         addr,
      Port:         port,
      ReadTimeOut:  readTimeOut,
      WriteTimeOut: writeTimeOut,
      TimeOut:      timeOut,
   }
}

func main() {
   server := NewServer("", "", 10*time.Second, 10*time.Second, 20*time.Second)
   fmt.Println(server)

   //默认值
   server2 := NewServer2()
   fmt.Println(server2)
   //改变addr,其他的不变
   server3 := NewServer2(WithAddr("127.0.0.1"))
   fmt.Println(server3)
}

//把server传进来
type Option func(*Server)

func WithAddr(addr string) Option {
   return func(s *Server) {
      //动态改变addr的值
      s.Addr = addr
   }
}

func WithPort(port string) Option {
   return func(s *Server) {
      s.Port = port
   }
}

func WithReadTimeOut(readTimeOut time.Duration) Option {
   return func(s *Server) {
      s.ReadTimeOut = readTimeOut
   }
}

func WithWriteTimeOut(writeTimeOut time.Duration) Option {
   return func(s *Server) {
      s.WriteTimeOut = writeTimeOut
   }
}

func WithTimeOut(timeOut time.Duration) Option {
   return func(s *Server) {
      s.TimeOut = timeOut
   }
}

func NewServer2(options ...Option) *Server {
   svr := &Server{
      Addr:         "localhost://",
      Port:         "8080",
      ReadTimeOut:  2 * time.Second,
      WriteTimeOut: 4 * time.Second,
      TimeOut:      10 * time.Second,
   }
   for _, option := range options {
      //去改变某个值,例Addr
      option(svr)
   }
   return svr
}