0x0
反射:
golang的reflect包实现了运行时的反射能力。reflect包中有两个重要函数:
reflect.TypeOf
获取数据类型信息,其类型为reflect.Type
reflect.ValueOf
获取数据运行时的信息,其类型为reflect.Value
Tag
golang的struct中的每一个字段(field
)后添加一段注释,称为 field tag
,最经典就是构建json的struct,例如:
type Login struct{
UserName string `json:"user_name"`
Password string `json:"password"`
}
其中 json:"user_name" json:"password"
就是 field tag
0x1
假设现有一 struct
:
type Note struct {
Time time.Time
Content string
Remarks string
}
我们想要指定一些字段非空,例如:Content != ""
按照一般通用的方法就是一个一个用if判断:
if content != "" { ... } else { ... }
如果只有几个字段需要这样判断还可以这样写。但如果有许多个字段或不同字段有不同类型,这样写的话就是一堆 if else
,就不是很优雅。
0x2
现在可以使用反射来更为优雅实现这一功能。只需要在struct需要非空的字段后添加一个 tag
来标记,这个tag
可以自定义,如:
type Note struct {
Time time.Time `must:"true"`
Content string `must:"true"`
Remarks string
}
其中 must:"true"
为我们自定义的tag
,表示该字段非空。
0x3
我们可以通过反射来获取struct
字段的tag
:
fmt.Println(reflect.TypeOf(¬e).Elem().Field(0).Tag.Get("must")) //获取第一个字段tag中"must"的值
0x4
完整实现代码:
type Note struct {
Time time.Time `must:"true"`
Content string `must:"true"`
Remarks string
}
func validator(value interface{}) {
val := reflect.ValueOf(value).Elem() //获取字段值
typ := reflect.TypeOf(value).Elem() //获取字段类型
// 遍历struct中的字段
for i := 0; i < typ.NumField(); i++ {
// 当struct中的tag为 must:"true" 且当前字段值为空值时,输出
if typ.Field(i).Tag.Get("must") == "true" && val.Field(i).IsZero() {
fmt.Println("Fail:", typ.Field(i).Name, "is null")
return
}
}
fmt.Println("Pass")
}
func main() {
note1 := Note{
Time: time.Now(),
Content: "content",
Remarks: "",
}
validator(¬e1)
// Pass
note2 := Note{
Time: time.Now(),
Content: "",
Remarks: "",
}
validator(¬e2)
// Fail: Content is null
}
One comment
称查重