七叶笔记 » golang编程 » Golang Option范式

Golang Option范式

我啥介绍Golang Option范式呢? 如果熟悉 containerd 代码就会发现,containerd里面大量地使用了这种编程范式,因为启动容器的参数非常多而且还有关联。它的主要场景就是优雅地设置复杂的各种关联属性,下面通过代码演示一下。

我们先定义一个简单的User 结构体

 type User struct {
Name      string
Role      string
MinSalary int
MaxSalary int
}  

通常我们会定义一个NewUser 方法去初始化这个结构体,返回一个指针,但我们这里需要各种自定义参数设置。比如,当我们定义这个用户的角色是 “经理” 的时候,那么他的薪资也需要设置成相应的值。

我们可以这样玩

先定义一个 UserOption 方法,方法只有一个参数,就是我们需要设置的 user。

 type UserOption func(user *User) error  

然后定义一个方法 遍历每一个 UserOption ,执行UserOption 方法。

 func BuildUser(opts ...UserOption) (*User, error) {
var user User
for _, opt := range opts {
err := opt(&user)
if err != nil {
return nil, err
}
}
return &user, nil
}  

这样,这个user 就可以被每个 UserOption 都改一遍了。

最后我们去实现两个 UserOption 测试一下

第一个 UserOption,非常简单,就是设置user name。

 func WithName(name string) UserOption {
return func(user *User) error {
user.Name = name
return nil
}
}  

第二个 UserOption ,如果是 经理 则设置薪资范围,如下;

 func WithRole(role string) UserOption {
return func(user *User) error {
// 校验角色
if role != "manager" && role != "sales" {
return errors.New("Invalid role!")
}
if role == "manager" {
user.MinSalary = 40000
user.MaxSalary = 60000
}
user.Role = role
return nil
}
}
  

最最后,在main里面就可以优雅地使用下面的方法创建一个复杂的 user 了。

 func main() {
user, err := BuildUser(
WithName("Michael Scott"),
WithRole("manager"),
)
if err != nil {
panic(err)
}
fmt.Println(user)
}  

大家都学会了吗 ?

相关文章