mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
fix validator
This commit is contained in:
parent
22f61f1c8a
commit
2a57def713
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
## 5.4.1 重构请求校验函数
|
## 5.4.1 重构请求校验函数
|
||||||
|
|
||||||
假设我们的数据已经通过某个binding库绑定到了具体的struct上。
|
假设我们的数据已经通过某个开源绑定库绑定到了具体的结构体上。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type RegisterReq struct {
|
type RegisterReq struct {
|
||||||
@ -42,7 +42,7 @@ func register(req RegisterReq) error{
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
我们用Go里成功写出了hadoken开路的箭头型代码。。这种代码一般怎么进行优化呢?
|
我们用Go里成功写出了波动拳开路的箭头型代码。。这种代码一般怎么进行优化呢?
|
||||||
|
|
||||||
很简单,在《重构》一书中已经给出了方案:[Guard Clauses](https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html)。
|
很简单,在《重构》一书中已经给出了方案:[Guard Clauses](https://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html)。
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ func register(req RegisterReq) error{
|
|||||||
|
|
||||||
## 5.4.2 用 validator 解放体力劳动
|
## 5.4.2 用 validator 解放体力劳动
|
||||||
|
|
||||||
从设计的角度讲,我们一定会为每个请求都声明一个struct。前文中提到的校验场景我们都可以通过validator完成工作。还以前文中的struct为例。为了美观起见,我们先把json tag省略掉。
|
从设计的角度讲,我们一定会为每个请求都声明一个结构体。前文中提到的校验场景我们都可以通过validator完成工作。还以前文中的结构体为例。为了美观起见,我们先把json tag省略掉。
|
||||||
|
|
||||||
这里我们引入一个新的validator库:
|
这里我们引入一个新的validator库:
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ fmt.Println(err)
|
|||||||
|
|
||||||
## 5.4.3 原理
|
## 5.4.3 原理
|
||||||
|
|
||||||
从结构上来看,每一个struct都可以看成是一棵树。假如我们有如下定义的struct:
|
从结构上来看,每一个结构体都可以看成是一棵树。假如我们有如下定义的结构体:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Nested struct {
|
type Nested struct {
|
||||||
@ -143,13 +143,13 @@ type T struct {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
把这个struct画成一棵树,见*图 5-11*:
|
把这个结构体画成一棵树,见*图 5-11*:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
*图 5-11 validator 树*
|
*图 5-11 validator 树*
|
||||||
|
|
||||||
从字段校验的需求来讲,无论我们采用深度优先搜索还是广度优先搜索来对这棵struct树来进行遍历,都是可以的。
|
从字段校验的需求来讲,无论我们采用深度优先搜索还是广度优先搜索来对这棵结构体树来进行遍历,都是可以的。
|
||||||
|
|
||||||
我们来写一个递归的深度优先搜索方式的遍历demo:
|
我们来写一个递归的深度优先搜索方式的遍历demo:
|
||||||
|
|
||||||
@ -235,8 +235,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
这里我们简单地对`eq=x`和`email`这两个tag进行了支持,读者可以对这个程序进行简单的修改以查看具体的validate效果。为了演示精简掉了错误处理和复杂case的处理,例如reflect.Int8/16/32/64,reflect.Ptr等类型的处理,如果给生产环境编写validate库的话,请务必做好功能的完善和容错。
|
这里我们简单地对`eq=x`和`email`这两个tag进行了支持,读者可以对这个程序进行简单的修改以查看具体的validate效果。为了演示精简掉了错误处理和复杂情况的处理,例如reflect.Int8/16/32/64,reflect.Ptr等类型的处理,如果给生产环境编写validate库的话,请务必做好功能的完善和容错。
|
||||||
|
|
||||||
在前一小节中介绍的validator组件在功能上要远比我们这里的demo复杂的多。但原理很简单,就是用reflect对struct进行树形遍历。有心的读者这时候可能会产生一个问题,我们对struct进行validate时大量使用了reflect,而go的reflect在性能上不太出众,有时甚至会影响到我们程序的性能。这样的考虑确实有一些道理,但需要对struct进行大量校验的场景往往出现在Web服务,这里并不一定是程序的性能瓶颈所在,实际的效果还是要从pprof中做更精确的判断。
|
在前一小节中介绍的validator组件在功能上要远比我们这里的例子复杂的多。但原理很简单,就是用反射对结构体进行树形遍历。有心的读者这时候可能会产生一个问题,我们对结构体进行validate时大量使用了反射,而go的反射在性能上不太出众,有时甚至会影响到我们程序的性能。这样的考虑确实有一些道理,但需要对结构体进行大量校验的场景往往出现在Web服务,这里并不一定是程序的性能瓶颈所在,实际的效果还是要从pprof中做更精确的判断。
|
||||||
|
|
||||||
如果基于反射的validator真的成为了你服务的性能瓶颈怎么办?现在也有一种思路可以避免反射:使用Go内置的parser对源代码进行扫描,然后根据struct的定义生成校验代码。我们可以将所有需要校验的结构体放在单独的package内。这就交给读者自己去探索了。
|
如果基于反射的validator真的成为了你服务的性能瓶颈怎么办?现在也有一种思路可以避免反射:使用Go内置的Parser对源代码进行扫描,然后根据结构体的定义生成校验代码。我们可以将所有需要校验的结构体放在单独的包内。这就交给读者自己去探索了。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user