需求分析:
假設現在一個對象的一些特性在初始化的時候,一般是有個默認值的。比如在我國的公安部門在爲一些人員登記信息的時候,這些人員的默認國籍大部分都會是中國,所以公安工作人員在錄入信息的時候系統自動默認錄入人員是中國人,除非必要否則並不需要修改,這樣減少了公安工作人員的工作量。再比如學校裏的學生的犯罪前科都是無的,這一欄默認無就行。
但是Go語言並沒有提供默認參數,一旦一個對象有很多屬性(這些屬性都可以有默認值)的時候,生成一個對象會變得及其麻煩。
比如我們要生成一個叫張三的人,當然張三還有其他的特性,比如身高,國籍,性別,年齡等,但是我們暫時除了他的名字之外啥都不知道,那麼我們可以將其他值設置爲一個默認的值。
type Person struct {
Name string
Age int
Country string
Gender string
Height int
Address string
}
func main() {
person := Person{
Name: "張三",
Age: -1, // 不知道默認-1, 不想默認值爲0
Country: "China", // 不知道,默認中國
Gender: "Male", // 不知道,默認男性
Height: -1, // 不知道,默認-1
Address: "unknown", // 不知道,直接填寫“unknown”
}
}
可以看到這樣寫的話初試化一個對象很長,特別是當一個對象有更多的特性的時候,上面的初始化會顯得冗長。
解決方案:函數式選項(Functional Options)
巧妙的利用了閉包和可變參數來做到給一個對象設置默認參數。具體解析在代碼註釋中。
package functionOptions
// 對象人
type Person struct {
Name string
Age int
Country string
Gender string
Height int
Address string
}
// 將func(*Person)這種類型的函數簡化下命名
type per func(*Person)
// 使用了閉包
func Country(country string) per {
return func(person *Person) {
person.Country = country
}
}
func Gender(gender string) per {
return func(person *Person) {
person.Gender = gender
}
}
func Address(address string) per {
return func(person *Person) {
person.Address = address
}
}
// 新建一個對象人,這個人必須有名字,其他的特性設置交給settings這可變參數中的閉包函數處理
func NewPerson(name string, settings ...per) *Person {
// 除了名字,都有默認值
person := &Person{
Name: name,
Age: -1,
Country: "China",
Gender: "Male",
Height: 0,
Address: "unknown",
}
// 遍歷可能存在所要設置的函數
for _, setting := range settings {
setting(person)
}
return person
}
用法:
package main
import (
"fmt"
op "studygo/pattern/functionOptions"
)
func main() {
person1 := op.NewPerson("張三")
fmt.Println(person1)
person2 := op.NewPerson("Mary", op.Gender("Female"), op.Country("Japan"))
fmt.Println(person2)
}
輸出結果對比:
&{張三 -1 China Male 0 unknown}
&{Mary -1 Japan Female 0 unknown}
參考文獻:https://books.studygolang.com/go-patterns/
撩我?
搜索我的公衆號:Kyda
或者掃描二維碼關注: