成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 語言開源項目使用的函數選項模式

開發 項目管理
本文我們介紹怎么使用 Go 語言的 “函數選項模式”,通過閱讀完本文所有內容,讀者朋友們應該已經感受到該模式的優點。

?1.介紹

在閱讀 Go 語言開源項目的源碼時,我們可以發現有很多使用 “函數選項模式”  的代碼,“函數選項模式” 是 Rob Pike 在 2014 年提出的一種模式,它使用 Go 語言的兩大特性,變長參數和閉包,可以使我們代碼更優雅。

關于變長參數和閉包的介紹,需要的讀者朋友們可以查閱歷史文章,本文我們介紹 “函數選項模式” 的相關內容。

2.使用方式

在介紹“函數選項模式”的使用方式之前,我們先閱讀以下這段代碼。

type User struct {
Id int
Name string
}

type option func(*User)

func (u *User) Option(opts ...option) {
for _, opt := range opts {
opt(u)
}
}

func WithId(id int) option {
return func(u *User) {
u.Id = id
}
}

func WithName(name string) option {
return func(u *User) {
u.Name = name
}
}

func main() {
u1 := &User{}
u1.Option(WithId(1))
fmt.Printf("%+v\n", u1)

u2 := &User{}
u2.Option(WithId(1), WithName("frank"))
fmt.Printf("%+v\n", u2)
}

輸出結果:

&{Id:1 Name:}
&{Id:1 Name:frank}

閱讀上面這段代碼,我們可以發現,首先,我們定義一個名字是 option 的類型,它實際上是一個可以接收一個參數的函數。

然后,我們給 User? 結構體定義一個 Option? 方法,該方法接收我們定義的 option? 類型的變長參數,方法體中使用 for-loop 執行函數。

定義 WithId? 函數和 WithName? 函數,設置 User? 結構體的字段 Id? 和字段 Name,該函數通過返回閉包的形式實現。

以上使用方式是 “函數選項模式” 的一般使用方式。該使用方式可以解決大部分問題,但是,“函數選項模式” 還有進階使用方式,感興趣的讀者朋友們可以繼續閱讀 Part 03 的內容。

3.進階使用方式

所謂 “函數選項模式” 的進階使用方式,即有返回值的 “函數選項模式”,其中,返回值包含 golang 內置類型和自定義 option 類型。

內置類型的返回值

type User struct {
Id int
Name string
}

type option func(*User) interface{}

func (u *User) Option(opts ...option) (id interface{}) {
for _, opt := range(opts) {
id = opt(u)
}
return id
}

func WithId(id int) option {
return func(u *User) interface{} {
prevId := u.Id
u.Id = id
return prevId
}
}

func main () {
u1 := &User{Id: 1}
id := u1.Option(WithId(2))
fmt.Println(id.(int))
fmt.Printf("%+v\n", u1)
}

輸出結果:

1
&{Id:2 Name:}

閱讀上面這段代碼,我們在定義 option 類型時,使用一個有返回值函數(此處使用的是空接口類型的返回值)。

WithId? 函數的函數體中的代碼也稍作修改,閉包中使用 prevId? 變量存儲結構體 User? 字段 Id 的原始數據,并作為函數返回值。

細心的讀者朋友們可能已經發現,我們在 main 函數中顯式處理返回值,即:

...
id := u1.Option(WithId(2))
fmt.Println(id.(int))
...

如果我們想要避免顯式處理返回值,可以使用返回自定義 option 類型的返回值的形式。

自定義 option 類型的返回值

type User struct {
Id int
Name string
}

type option func(*User) option

func (u *User) Option(opts ...option) (prev option) {
for _, opt := range opts {
prev = opt(u)
}
return prev
}

func WithId(id int) option {
return func(u *User) option {
prevId := u.Id
u.Id = id
return WithId(prevId)
}
}

func main () {
u1 := &User{Id: 1}
prev := u1.Option(WithId(2))
fmt.Printf("%+v\n", u1)
u1.Option(prev)
fmt.Printf("%+v\n", u1)
}

輸出結果:

&{Id:2 Name:}
&{Id:1 Name:}

閱讀上面這段代碼,我們在定義 option? 類型時,通過把函數的返回值更改為 option? 類型,我們就可以在 WithId? 函數中,使用閉包處理 User? 結構體 Id 字段的原始值。

需要注意的是, User? 結構體 Option? 方法的返回值是  option 類型。

4.使用示例

我們在了解完 “函數選項模式” 之后,使用該模式實現一個簡單示例。

type User struct {
Id int
Name string
Email string
}

type option func(*User)

func WithId(id int) option {
return func(u *User) {
u.Id = id
}
}

func WithName(name string) option {
return func(u *User) {
u.Name = name
}
}

func WithEmail(email string) option {
return func(u *User) {
u.Email = email
}
}

func NewUser(opts ...option) *User {
const (
defaultId = -1
defaultName = "guest"
defaultEmail = "undefined"
)
u := &User{
Id: defaultId,
Name: defaultName,
Email: defaultEmail,
}

for _, opt := range opts {
opt(u)
}
return u
}

func main() {
u1 := NewUser(WithName("frank"), WithId(1000000001))
fmt.Printf("%+v\n", u1)
u2 := NewUser(WithEmail("gopher@88.com"))
fmt.Printf("%+v\n", u2)
u3 := NewUser()
fmt.Printf("%+v\n", u3)
}

輸出結果:

&{Id:1000000001 Name:frank Email:undefined}
&{Id:-1 Name:guest Email:gopher@88.com}
&{Id:-1 Name:guest Email:undefined}

閱讀上面這段代碼,我們使用 “函數選項模式” 實現構造函數 NewUser,不僅可以自定義默認值(避免使用 Go 類型零值作為默認值),而且還可以使調用者靈活傳參(無需關心參數的順序和個數)。

5.總結

本文我們介紹怎么使用 Go 語言的 “函數選項模式”,通過閱讀完本文所有內容,讀者朋友們應該已經感受到該模式的優點。

但是,該模式也有缺點,比如需要定義 WithXxx 函數,增加了代碼量。

所以,我們可以根據實際使用場景決定是否選擇使用 “函數選項模式”。

責任編輯:武曉燕 來源: Golang語言開發棧
相關推薦

2021-11-28 22:33:01

Go選項模式

2022-07-03 23:07:48

Go語言參數

2022-07-04 14:41:31

Go 語言變長參數變長參數函數

2018-09-20 17:30:01

2013-05-28 09:43:38

GoGo語言并發模式

2022-04-13 08:20:32

DockerGo項目

2021-04-13 07:58:42

Go語言函數

2009-12-28 09:09:34

Google開源項目

2019-01-22 15:32:05

Go語言工具開發

2019-04-26 09:37:30

Go 開源技術

2022-07-19 12:25:29

Go

2024-08-19 10:29:26

SQL加密選項模式綁定

2023-03-21 07:57:37

Go語言設計模式

2022-03-13 23:51:39

Web項目Go

2022-05-16 10:58:12

Go 項目Makefilemake

2019-10-14 08:00:00

Go語言編程語言開源項目

2023-03-27 00:20:48

2022-10-09 08:48:13

配置化建造者參數

2022-03-27 23:11:39

Go語言函數

2021-10-16 17:53:35

Go函數編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品美女久久久久aⅴ国产馆 | 99精品国产成人一区二区 | 一级做受毛片免费大片 | 久久免费香蕉视频 | 国产免费一区二区三区 | 亚洲精品美女视频 | 欧美激情一区二区三区 | 色视频一区二区 | 国产成人精品视频在线观看 | 久久男人| 综合一区二区三区 | 成人黄色网址大全 | 精品精品 | 国产成人精品一区二区三区视频 | 在线免费观看成人 | 99精品国产一区二区三区 | 国产精品日韩一区 | 国产免费又色又爽又黄在线观看 | 粉嫩粉嫩芽的虎白女18在线视频 | 综合一区 | 亚州精品天堂中文字幕 | 国产偷录视频叫床高潮对白 | 欧美成人性生活 | 国户精品久久久久久久久久久不卡 | 日日精品 | 国产一区二区 | 亚洲精品一区二区三区在线观看 | 欧美精品一区三区 | 国产精品av久久久久久毛片 | 大吊一区二区 | 国产免费国产 | 伊伊综合网 | 色综合视频 | 日韩精品在线一区二区 | 亚洲国产精品一区二区三区 | 亚洲精品免费观看 | av一区二区三区四区 | 精品国产乱码久久久久久闺蜜 | 北条麻妃一区二区三区在线视频 | 美女黄视频网站 | 九九九视频在线观看 |