Golang编程模式:函数式编程(function options)

Golang编程模式:函数式编程(function options)
1.配置选项问题
1.golang编程时 我们经常需要对一个对象或者业务实体进行相关的配置 对相应的结构体进行初始化,下面是结构题例子
type Server struct {
    Addr     string
    Port     int
    Protocol string
    Timeout  time.Duration
    MaxConns int
    TLS      *tls.Config
}

1.1 我们对结构题初始化赋值,可能会考虑
1.2 sever监听的Addr和Port不能为空
1.3 其它字段比如协议 Protocol可以默认TCP 最大连接数MaxConns默认10241.4 TLS安全连接可以为nil
2.针对上述情况 我们需要多种不同的创建配置
2.1.比如地址端口必须 就创建
func NewDefaultServer(addr string, port int) *Server{
  return &Server{addr, port, "tcp", 30 * time.Second, 100, nil}
}

2.2.配置TLS
func NewTLSServer(addr string, port int, tls *tls.Config) *Server {
  return &Server{addr, port, "tcp", 30 * time.Second, 100, tls}
}


2.3.配置timeout
func NewServerWithTimeout(addr string, port int, timeout time.Duration) *Server {
  return &Server{addr, port, "tcp", timeout, 100, nil}
}

2.4.配置更多的参数
func NewTLSServerWithMaxConnAndTimeout(addr string, port int, maxconns int, timeout time.Duration, tls *tls.Config) *Server {
  return &Server{addr, port, "tcp", 30 * time.Second, maxconns, tls}
}
go语言不支持重载函数 不同的函数名对应不同的配置项,这样就会容易犯错
3.优化方式例如下面所示
3.1.将变动的参数放到同一结构体 这样代码就看起来简洁多了
type Server struct {
    Addr string
    Port int
    Conf *Config
}


type Config struct {
    Protocol string
    Timeout  time.Duration
    Maxconns int
    TLS      *tls.Config
}


func NewServer(addr string, port int, conf *Config) *Server {
    //...
}

//使用默认 config为空
srv1, _ := NewServer("localhost", 9000, nil) 

//config初始化
conf := Config{Protocol:"tcp", Timeout: 60*time.Duration}
srv2, _ := NewServer("locahost", 9000, &conf)

3.2.但是上面的优化还不够装杯,后来我们在看源码(比如gin 比如mq)的时候会看到函数式编程
那就让我们看看什么是函数式编程,以后出去好装杯,当然更重要的是提升我们的代码能力
4.函数式编程
4.1.定义新函数类型
type Option func(*Server)
4.2.使用函数式的方式定义一组函数

func Protocol(p string) Option {
    return func(s *Server) {
        s.Protocol = p
    }
}
func Timeout(timeout time.Duration) Option {
    return func(s *Server) {
        s.Timeout = timeout
    }
}
func MaxConns(maxconns int) Option {
    return func(s *Server) {
        s.MaxConns = maxconns
    }
}
func TLS(tls *tls.Config) Option {
    return func(s *Server) {
        s.TLS = tls
    }
}
4.3.这样的函数简介明了 传入一个参数 通过返回的函数设置自己的server参数
4.4.例如我们调用MaxConns(30) 返回值是一个 func(s *Server) {s.MaxConns = 30}的函数
4.5.现在我们在定义一个整体的NewServer函数,加上一个可变传参options
func NewServer(addr string, port int, options ...Option) *Server {

  server := Server{
    Addr:     addr,
    Port:     port,
    Protocol: "tcp",
    Timeout:  30 * time.Second,
    MaxConns: 1000,
    TLS:      nil,
  }
  for _, option := range options {
    option(&srv)
  }
  //...
  return &server
}
4.6.再初始化的时候就简洁明了,用什么拿什么 
s1, _ := NewServer("localhost", 1024)
s2, _ := NewServer("localhost", 2048, Protocol("udp"))
s3, _ := NewServer("0.0.0.0", 8080, Timeout(300*time.Second), MaxConns(1000))
总结
这就是函数式编程 使得开发更简单 用什么拿什么 新手来了也不会纠结怎么定义新配置函数名称 直接用就行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值