成人免费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-04 14:41:31

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

2022-07-03 23:07:48

Go語言參數

2018-09-20 17:30:01

2013-05-28 09:43:38

GoGo語言并發模式

2022-04-13 08:20:32

DockerGo項目

2019-01-22 15:32:05

Go語言工具開發

2019-04-26 09:37:30

Go 開源技術

2009-12-28 09:09:34

Google開源項目

2021-04-13 07:58:42

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語言編程語言開源項目

2022-10-09 08:48:13

配置化建造者參數

2023-03-27 00:20:48

2022-03-27 23:11:39

Go語言函數

2020-03-06 10:54:51

Go語言XML算法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 黄色欧美在线 | 一区二区三区四区五区在线视频 | 在线午夜| 亚洲永久 | www.日韩高清 | 午夜日韩 | 日韩精品一区二区三区中文在线 | 91av导航 | 成年精品| 欧美日韩国产一区二区三区 | 国产资源在线观看 | 日韩欧美在线观看一区 | 国产黄色在线观看 | 粉嫩国产精品一区二区在线观看 | 国产免费一区二区三区网站免费 | www.中文字幕 | 永久精品 | av一区二区在线观看 | 99久久免费精品国产男女高不卡 | 国产视频黄色 | 日韩欧美三级 | 蜜桃视频在线观看www社区 | 日本成人在线观看网站 | 亚洲一区免费在线 | 日本在线综合 | 综合久| 国产免费一区二区 | 欧美久久一级 | 婷婷综合 | 一区二区免费在线观看 | 欧产日产国产精品国产 | 欧美1区 | 久久久高清 | 在线免费国产视频 | 天天拍天天插 | 日韩精品av| 午夜电影一区 | 久久国产综合 | 99热在线免费 | 99精品99| 亚洲国产精品久久久久 |