mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
update validator
This commit is contained in:
parent
6d6584aaaa
commit
1dd1615f19
@ -122,3 +122,86 @@ fmt.Println(err) // Key: 'RegisterReq.PasswordRepeat' Error:Field validation for
|
|||||||
如果觉得这个 validator 提供的错误信息不够人性化,例如要把错误信息返回给用户,那就不应该直接显示英文了。可以针对每种 tag 进行错误信息订制,读者可以自行探索。
|
如果觉得这个 validator 提供的错误信息不够人性化,例如要把错误信息返回给用户,那就不应该直接显示英文了。可以针对每种 tag 进行错误信息订制,读者可以自行探索。
|
||||||
|
|
||||||
## 原理
|
## 原理
|
||||||
|
|
||||||
|
从结构上来看,每一个 struct 都可以看成是一棵树。从字段校验这个角度来讲,无论我们采用深度优先搜索还是广度优先搜索来对这棵 struct 树来进行遍历,都是可以的。
|
||||||
|
|
||||||
|
我们来写一个递归的深度优先搜索方式的遍历 demo:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Nested struct {
|
||||||
|
Email string `validate:"email"`
|
||||||
|
}
|
||||||
|
type T struct {
|
||||||
|
Age int `validate:"eq=10"`
|
||||||
|
Nested Nested
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateEmail(input string) bool {
|
||||||
|
if pass, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, input); pass {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(v interface{}) (bool, string) {
|
||||||
|
validateResult := true
|
||||||
|
errmsg := "success"
|
||||||
|
vt := reflect.TypeOf(v)
|
||||||
|
vv := reflect.ValueOf(v)
|
||||||
|
for i := 0; i < vv.NumField(); i++ {
|
||||||
|
fieldVal := vv.Field(i)
|
||||||
|
tagContent := vt.Field(i).Tag.Get("validate")
|
||||||
|
k := fieldVal.Kind()
|
||||||
|
|
||||||
|
switch k {
|
||||||
|
case reflect.Int:
|
||||||
|
val := fieldVal.Int()
|
||||||
|
tagValStr := strings.Split(tagContent, "=")
|
||||||
|
tagVal, _ := strconv.ParseInt(tagValStr[1], 10, 64)
|
||||||
|
if val != tagVal {
|
||||||
|
errmsg = "validate int failed, tag is: "+ tagVal)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
val := fieldVal.String()
|
||||||
|
tagValStr := tagContent
|
||||||
|
switch tagValStr {
|
||||||
|
case "email":
|
||||||
|
nestedResult := validateEmail(val)
|
||||||
|
if nestedResult == false {
|
||||||
|
errmsg = "validate mail failed, field val is: "+ val
|
||||||
|
validateResult = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
valInter := fieldVal.Interface()
|
||||||
|
nestedResult := validate(valInter)
|
||||||
|
if nestedResult == false {
|
||||||
|
validateResult = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validateResult
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var a = T{Age: 10, Nested: Nested{Email: "abc@abc.com"}}
|
||||||
|
|
||||||
|
validateResult := validate(a)
|
||||||
|
fmt.Println(validateResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
这里我们简单地对 eq=x 和 email 这两个 tag 进行了支持,读者可以对这个程序进行简单的修改以查看具体的 validate 效果。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user