在编程中,我们经常需要对一个对象进行相关的配置。比如新增员工,我们需要填写姓名、年龄、邮箱等;但是对于座机、性别可能就不是必填选项,如下代码示例:
type User struct {
Name string
Age int
Email string
Phone string
//...Other
School string
Gender string
}
在其他面向对象的语言中,如Java,我们可以通过重载函数解决初始化参数问题。因为 Go 语言不支持重载函数,所以,你得用不同的函数名来应对不同的配置选项。
func NewDefaultUser(name string, age int, email string) (*User, error) {
return &User{Name: name, Age: age, Email: email}, nil
}
func NewPhoneUser(name string, age int, email string, phone string) (*Server, error) {
return &User{Name: name, Age: age, Email: email, Phone: phone}, nil
}
Builder 模式
Java 程序员,一定会很自然地使用 Builder 模式。
User user = new User.Builder()
.name("Moonus")
.email("moonus@outlook.com")
.age(18)
.build();
Functional Options
// UserOption 我们定义一个函数类型,类似C#与委托函数Action
type UserOption func(*User)
然后,我们可以使用函数式的方式定义一组如下的函数:
func Phone(phone string) UserOption {
return func(user *User) {
user.Phone = phone
}
}
func School(school string) UserOption {
return func(user *User) {
user.School = school
}
}
func Gender(gender string) UserOption {
return func(user *User) {
user.Gender = gender
}
}
通过可变参数 options,for-loop 来设置我们的 User 对象。
func CreateUser(name string, age int, email string, opt ...UserOption) User {
user := User{Name: name, Age: age, Email: email}
for _, option := range opt {
option(&user)
}
return user
}
func TestUser(t *testing.T) {
user := CreateUser("Moonus", 18, "Moonus@outlook.com", Phone("110"), func(user2 *User) {
user2.Gender = "男"
})
fmt.Println(user)
}
Functional Options通过函数式,可以帮助开发者更加灵活得初始化对象,易于扩展。比如初始化对象我们需要设置默认值,通过该设计能快速解决该问题。