[Golang] Design Pattern
Functional Options
資料來源:GO 程式設計模式:FUNCTIONAL OPTIONS @ 陳皓
在 Go 中需要為某些 struct (通常是一些設定),可以同時有預設值的,但有希望可以客製化設定時,可以使用這個方式:
- 定義需要可以被 config 的 struct,例如
Server
- 定義一個能夠接收 *Server 為參數的型別,例如
Option
- 定義許多能夠修改 Server 欄位值的函式,例如
Protocol
,Timeout
, 等等 - 定義
NewServer
函式,在這個函式中會有 Server 的預設值,並且可以透過呼叫函式修改設定
// 程式碼來源:https://coolshell.cn/articles/21146.html
// @ 陳皓
// Server 定義可以接收的參數欄位
type Server struct {
Addr string
Port int
Protocol string
Timeout time.Duration
Maxconns int
TLS *tls.Config
}
// Option 的型別是可以接受 *Server 為參數的函式
type Option func(*Server)
// Protocol 用來為 Server 添加 Protocol 欄位
func Protocol(p string) Option {
return func(s *Server) {
s.Protocol = p
}
}
// Timeout 用來為 Server 添加 Timeout 欄位
func Timeout(timeout time.Duration) Option {
return func(s *Server) {
s.Timeout = timeout
}
}
// MaxConns 用來為 Server 添加 MaxConns 欄位
func MaxConns(maxconns int) Option {
return func(s *Server) {
s.Maxconns = maxconns
}
}
// TLS 用來為 Server 添加 TLS 欄位
func TLS(tls *tls.Config) Option {
return func(s *Server) {
s.TLS = tls
}
}
// NewServer 用來建立 Server 物件,並可以根據 options 回傳
func NewServer(addr string, port int, options ...func(*Server)) (*Server, error) {
// server 的預設值定在這
server := Server{
Addr: addr,
Port: port,
Protocol: "tcp",
Timeout: 30 * time.Second,
Maxconns: 1000,
TLS: nil,
}
for _, option := range options {
option(&server)
}
return &server, nil
}
func main() {
s1, _ := NewServer("localhost", 1024)
fmt.Printf("server 1: %+v \n", s1)
s2, _ := NewServer("localhost", 2048, Protocol("udp"))
fmt.Printf("server 1: %+v \n", s2)
s3, _ := NewServer("localhost", 8080, Timeout(300*time.Second), MaxConns(1000))
fmt.Printf("server 1: %+v \n", s3)
}