Loading... # 0x0 ## 反射: golang的reflect包实现了运行时的反射能力。reflect包中有两个重要函数: - `reflect.TypeOf` 获取数据类型信息,其类型为`reflect.Type` - `reflect.ValueOf` 获取数据运行时的信息,其类型为`reflect.Value` ## Tag golang的struct中的每一个字段(`field`)后添加一段注释,称为 `field tag`,最经典就是构建json的struct,例如: ```go type Login struct{ UserName string `json:"user_name"` Password string `json:"password"` } ``` 其中 `json:"user_name" json:"password"`就是 `field tag` # 0x1 假设现有一 `struct`: ```go type Note struct { Time time.Time Content string Remarks string } ``` 我们想要指定一些字段非空,例如:`Content != ""` 按照一般通用的方法就是一个一个用if判断: ```go if content != "" { ... } else { ... } ``` 如果只有几个字段需要这样判断还可以这样写。但如果有许多个字段或不同字段有不同类型,这样写的话就是一堆 `if else`,就不是很优雅。 # 0x2 现在可以使用反射来更为优雅实现这一功能。只需要在struct需要非空的字段后添加一个 `tag`来标记,这个`tag`可以自定义,如: ```go type Note struct { Time time.Time `must:"true"` Content string `must:"true"` Remarks string } ``` 其中 `must:"true"`为我们自定义的`tag`,表示该字段非空。 # 0x3 我们可以通过反射来获取`struct`字段的`tag`: ```go fmt.Println(reflect.TypeOf(¬e).Elem().Field(0).Tag.Get("must")) //获取第一个字段tag中"must"的值 ``` # 0x4 完整实现代码: ```go 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 } ``` Last modification:August 20, 2021 © Allow specification reprint Support Appreciate the author AliPayWeChat Like 0 如果觉得我的文章对你有用,请随意赞赏
One comment
称查重