grpc中优雅实现默认参数实现分析

在学习go-grpc源码过程中发现,发现grpc有很优雅的实现值得学习,在此做下记录

应用场景:如果你定义的结构有些扩展的默认参数,不需要调用者传入,或只需要特定的使用者做修改时

一般我们实现方式是

 type Server struct {
  Name string
  Url string
  Timeout int  //扩展参数
 }
 ​
 func NewServer(name, url string, timeout int) *Server {
  if timeout == 0 {
  timeout = 10
  }
  
  return &Server{
  Name:    name,
  Url:     url,
  Timeout: timeout,
  }
 }

这样做的优点是简单易懂,在简单使用时这样没有问题,但这样代码侵入性强,如果后期要增加参数,需要再修改代码,而且每次都需要传入所有参数,如果有很多其他参数,这样写就显得不够优雅

我们看下grpc的实现方式,如下,我写了个例子

 type Server struct {
  Name string
  Url string
  Timeout int  //扩展参数
 }
 ​
 type ServerOptionInf interface {
  initServer(*Server)
 }
 ​
 func NewServer(name, url string, o ...ServerOptionInf)  *Server {
  s := Server{
  Name:    name,
  Url:     url,
  Timeout: 10,
  }
 ​
  for _, v := range o {
  v.initServer(&s)
  }
  return &s
 }
 ​
 type OptionFunc func(*Server)
 ​
 type ServerOption struct {
  f OptionFunc
 }
 ​
 func (so *ServerOption)initServer(s *Server)  {
  so.f(s)
 }
 ​
 func WithTimeoutOption(timeout int) ServerOptionInf {
  return &ServerOption{f: func(server *Server) {
  server.Timeout = timeout
  }}
 }

 type Server struct {
  Name string
  Url string
  Timeout int  //扩展参数
 }
 ​
 type OptionFunc func(*Server)
 ​
 func NewServer(name, url string, op ...OptionFunc) *Server {
  s := Server{
  Name:    name,
  Url:     url,
  Timeout: 10,
  }
 ​
  for _, v := range op {
  v(&s)
  }
  return &s
 }
 ​
 func WithTimeoutOption(timeout int) OptionFunc {
  return  func(server *Server) {
  server.Timeout = timeout
  }
 }

从代码可以看出 NewServer 是创建新对象的方法,但除了传必要参数外,只传了ServerOptionInf 接口的 数组,在创建出事化的时候调用接口 的函数,初始化其他参数,这样就可以在创建新对象可变的修改默认值。

当然还有简单点的实现方式,不需要使用接口,直接定义函数方式


type Server struct {
   Name string
   Url string
   Timeout int  //扩展参数
}

type OptionFunc func(*Server)

func NewServer(name, url string, op ...OptionFunc) *Server {
   s := Server{
       Name:    name,
       Url:     url,
       Timeout: 10,
   }

   for _, v := range op {
       v(&s)
   }
   return &s
}

func WithTimeoutOption(timeout int) OptionFunc {
   return  func(server *Server) {
       server.Timeout = timeout
   }
}

WithTimeoutOption使用了golang 的闭包特性,直接返回操作初始化成员的函数。

你可能感兴趣的:(grpc,golang,源码)