目錄html
更新、更全的《Go從入門到放棄》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-mxrjjcnn-hn.htmlpython
本文主要介紹了Go語言中函數式選項模式及該設計模式在實際編程中的應用。git
最近看go-micro/options.go源碼的時候,發現了一段關於服務註冊的代碼以下:github
type Options struct { Broker broker.Broker Cmd cmd.Cmd Client client.Client Server server.Server Registry registry.Registry Transport transport.Transport // Before and After funcs BeforeStart []func() error BeforeStop []func() error AfterStart []func() error AfterStop []func() error // Other options for implementations of the interface // can be stored in a context Context context.Context } func newOptions(opts ...Option) Options { opt := Options{ Broker: broker.DefaultBroker, Cmd: cmd.DefaultCmd, Client: client.DefaultClient, Server: server.DefaultServer, Registry: registry.DefaultRegistry, Transport: transport.DefaultTransport, Context: context.Background(), } for _, o := range opts { o(&opt) } return opt }
當時呢,也不是很明白newOptions
這個構造函數爲何要這麼寫,可是後面在微信羣裏看到有人也再發相似的代碼問爲何要這麼寫,後來在羣裏討論的時候才知道了這是一種設計模式–函數式選項模式。golang
可能你們看到如今也不是很明白我說的問題究竟是什麼,我把它簡單提煉一下。編程
咱們如今有一個結構體,定義以下:設計模式
type Option struct { A string B string C int }
如今咱們須要爲其編寫一個構造函數,咱們可能會寫成下面這種方式:bash
func newOption(a, b string, c int) *Option { return &Option{ A: a, B: b, C: c, } }
上面的代碼很好理解,也是咱們一直在寫的。有什麼問題嗎?微信
咱們如今來思考如下兩個問題:閉包
咱們先定義一個OptionFunc
的函數類型
type OptionFunc func(*Option)
而後利用閉包爲每一個字段編寫一個設置值的With函數:
func WithA(a string) OptionFunc { return func(o *Option) { o.A = a } } func WithB(b string) OptionFunc { return func(o *Option) { o.B = b } } func WithC(c int) OptionFunc { return func(o *Option) { o.C = c } }
而後,咱們定義一個默認的Option
以下:
var ( defaultOption = &Option{ A: "A", B: "B", C: 100, } )
最後編寫咱們新版的構造函數以下:
func newOption2(opts ...OptionFunc) (opt *Option) { opt = defaultOption for _, o := range opts { o(opt) } return }
測試一下:
func main() { x := newOption("nazha", "小王子", 10) fmt.Println(x) x = newOption2() fmt.Println(x) x = newOption2( WithA("沙河娜扎"), WithC(250), ) fmt.Println(x) }
輸出:
&{nazha 小王子 10} &{A B 100} &{沙河娜扎 B 250}
這樣一個使用函數式選項設計模式的構造函數就實現了。這樣默認值也有了,之後再要爲Option添加新的字段也不會影響以前的代碼。
推薦閱讀: