Go函数式选项模式
一.引入
在编写代码时,当我们通过一个结果体构造一个新的对象时,往往会像下边这样,但如果结构体中有很多的字段,而且在构造新对象时只需要修改很少的字段,其它字段都使用默认值,用下边这种方式就会显得很笨重,这里我们就可以引入函数式选项模式的概念.
type student struct {
name string
age int
class string
}
func main() {
stu := student{"Alex", 20, "math"}
stu2 := student{
name: "alex",
age: 40,
}
}
Functional options 是一种模式,在该模式中,你可以声明一个不透明的
Option
类型,该类型在某些内部结构中记录信息。你接受这些可变数量的选项,并根据内部结构上的选项记录的完整信息进行操作。将此模式用于构造函数和其他公共 API 中的可选参数,你预计这些参数需要扩展,尤其是在这些函数上已经有三个或更多参数的情况下。
二.示例
type student struct {
name string
age int
class string
}
type stuOption func(*student)
func withAge(a int) stuOption {
// 设置年龄
return func(s *student) {
s.age = a
}
}
func withClass(c string) stuOption {
// 设置课程
return func(s *student) {
s.class = c
}
}
func newStudent(name string, options ...stuOption) *student {
stu := &student{name: name, age: 20, class: "math"} // 年龄默认为20,课程默认为math
for _, o := range options {
o(stu)
}
return stu
}
func main() {
s := newStudent("Lilith", withAge(10))
s2 := newStudent("Ulrica", withAge(100), withClass("chinese"))
fmt.Println(*s) // {Lilith 10 math}
fmt.Println(*s2) // {Ulrica 100 chinese}
}
上边代码中我们通过with*的形式给结构体变量赋值,在调用newStudent函数时,如果没有指定除name外的变量值就使用默认值,如s未指定class的值,结果class为默认值math,这样就可以更加灵活的对结构体进行修改,添加结构体变量时只需添加对应的with*函数即可.