自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 語(yǔ)言開(kāi)源項(xiàng)目使用的函數(shù)選項(xiàng)模式

開(kāi)發(fā) 項(xiàng)目管理
本文我們介紹怎么使用 Go 語(yǔ)言的 “函數(shù)選項(xiàng)模式”,通過(guò)閱讀完本文所有內(nèi)容,讀者朋友們應(yīng)該已經(jīng)感受到該模式的優(yōu)點(diǎn)。

?1.介紹

在閱讀 Go 語(yǔ)言開(kāi)源項(xiàng)目的源碼時(shí),我們可以發(fā)現(xiàn)有很多使用 “函數(shù)選項(xiàng)模式”  的代碼,“函數(shù)選項(xiàng)模式” 是 Rob Pike 在 2014 年提出的一種模式,它使用 Go 語(yǔ)言的兩大特性,變長(zhǎng)參數(shù)和閉包,可以使我們代碼更優(yōu)雅。

關(guān)于變長(zhǎng)參數(shù)和閉包的介紹,需要的讀者朋友們可以查閱歷史文章,本文我們介紹 “函數(shù)選項(xiàng)模式” 的相關(guān)內(nèi)容。

2.使用方式

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

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)
}

輸出結(jié)果:

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

閱讀上面這段代碼,我們可以發(fā)現(xiàn),首先,我們定義一個(gè)名字是 option 的類型,它實(shí)際上是一個(gè)可以接收一個(gè)參數(shù)的函數(shù)。

然后,我們給 User? 結(jié)構(gòu)體定義一個(gè) Option? 方法,該方法接收我們定義的 option? 類型的變長(zhǎng)參數(shù),方法體中使用 for-loop 執(zhí)行函數(shù)。

定義 WithId? 函數(shù)和 WithName? 函數(shù),設(shè)置 User? 結(jié)構(gòu)體的字段 Id? 和字段 Name,該函數(shù)通過(guò)返回閉包的形式實(shí)現(xiàn)。

以上使用方式是 “函數(shù)選項(xiàng)模式” 的一般使用方式。該使用方式可以解決大部分問(wèn)題,但是,“函數(shù)選項(xiàng)模式” 還有進(jìn)階使用方式,感興趣的讀者朋友們可以繼續(xù)閱讀 Part 03 的內(nèi)容。

3.進(jìn)階使用方式

所謂 “函數(shù)選項(xiàng)模式” 的進(jìn)階使用方式,即有返回值的 “函數(shù)選項(xiàng)模式”,其中,返回值包含 golang 內(nèi)置類型和自定義 option 類型。

內(nèi)置類型的返回值

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)
}

輸出結(jié)果:

1
&{Id:2 Name:}

閱讀上面這段代碼,我們?cè)诙x option 類型時(shí),使用一個(gè)有返回值函數(shù)(此處使用的是空接口類型的返回值)。

WithId? 函數(shù)的函數(shù)體中的代碼也稍作修改,閉包中使用 prevId? 變量存儲(chǔ)結(jié)構(gòu)體 User? 字段 Id 的原始數(shù)據(jù),并作為函數(shù)返回值。

細(xì)心的讀者朋友們可能已經(jīng)發(fā)現(xiàn),我們?cè)?nbsp;main 函數(shù)中顯式處理返回值,即:

...
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)
}

輸出結(jié)果:

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

閱讀上面這段代碼,我們?cè)诙x option? 類型時(shí),通過(guò)把函數(shù)的返回值更改為 option? 類型,我們就可以在 WithId? 函數(shù)中,使用閉包處理 User? 結(jié)構(gòu)體 Id 字段的原始值。

需要注意的是, User? 結(jié)構(gòu)體 Option? 方法的返回值是  option 類型。

4.使用示例

我們?cè)诹私馔?“函數(shù)選項(xiàng)模式” 之后,使用該模式實(shí)現(xiàn)一個(gè)簡(jiǎn)單示例。

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)
}

輸出結(jié)果:

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

閱讀上面這段代碼,我們使用 “函數(shù)選項(xiàng)模式” 實(shí)現(xiàn)構(gòu)造函數(shù) NewUser,不僅可以自定義默認(rèn)值(避免使用 Go 類型零值作為默認(rèn)值),而且還可以使調(diào)用者靈活傳參(無(wú)需關(guān)心參數(shù)的順序和個(gè)數(shù))。

5.總結(jié)

本文我們介紹怎么使用 Go 語(yǔ)言的 “函數(shù)選項(xiàng)模式”,通過(guò)閱讀完本文所有內(nèi)容,讀者朋友們應(yīng)該已經(jīng)感受到該模式的優(yōu)點(diǎn)。

但是,該模式也有缺點(diǎn),比如需要定義 WithXxx 函數(shù),增加了代碼量。

所以,我們可以根據(jù)實(shí)際使用場(chǎng)景決定是否選擇使用 “函數(shù)選項(xiàng)模式”。

責(zé)任編輯:武曉燕 來(lái)源: Golang語(yǔ)言開(kāi)發(fā)棧
相關(guān)推薦

2021-11-28 22:33:01

Go選項(xiàng)模式

2022-07-03 23:07:48

Go語(yǔ)言參數(shù)

2022-07-04 14:41:31

Go 語(yǔ)言變長(zhǎng)參數(shù)變長(zhǎng)參數(shù)函數(shù)

2018-09-20 17:30:01

2022-04-13 08:20:32

DockerGo項(xiàng)目

2013-05-28 09:43:38

GoGo語(yǔ)言并發(fā)模式

2021-04-13 07:58:42

Go語(yǔ)言函數(shù)

2009-12-28 09:09:34

Google開(kāi)源項(xiàng)目

2019-01-22 15:32:05

Go語(yǔ)言工具開(kāi)發(fā)

2019-04-26 09:37:30

Go 開(kāi)源技術(shù)

2022-07-19 12:25:29

Go

2024-08-19 10:29:26

SQL加密選項(xiàng)模式綁定

2023-03-21 07:57:37

Go語(yǔ)言設(shè)計(jì)模式

2022-03-13 23:51:39

Web項(xiàng)目Go

2022-05-16 10:58:12

Go 項(xiàng)目Makefilemake

2023-03-27 00:20:48

2021-10-16 17:53:35

Go函數(shù)編程

2024-01-06 08:16:19

init?函數(shù)數(shù)據(jù)開(kāi)發(fā)者

2019-10-14 08:00:00

Go語(yǔ)言編程語(yǔ)言開(kāi)源項(xiàng)目

2022-03-27 23:11:39

Go語(yǔ)言函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)