在Golang的日常开发中,有时候需要对struct
的每个字段(field)进行校验,从而判断结构体的值是否符合条件。
考虑下面的profile
结构体:
1 | type profile struct { |
对于profile
类型的值,有下面的限制:
Info
字段Info
不为nilName
的长度限制为[1,20]Age
的取值范围是[18,80]Email
的长度限制为[1,64], 并且符合邮箱的格式
Companies
字段Position
只能是frontend或者backend- 如果
Position
是frontend, 里面的元素取值只能是 html,css,javascript. - 如果
Position
是backend, 里面的元素取值只能是 C,Cpp,Java,Golang.
Skills
的长度限制为[1,3]
下面分别讲述使用if/else
, gin的校验器,和checker,三个方法对结构体参数进行校验。
使用if/else
使用if/else
判断‘结构体参数是否合法。
1 | func isValidProfile(pro profile) bool { |
可以看到,对于上述的校验规则,可能需要写大段的if/else
判断语句,当语句太长时,不适合阅读,并且与结构体强耦合。
使用go.pkg的validatior
go.pkg
的validator,它是通过在结构体的字段添加标签(tag),来校验结构体。
profile
结构体要改造成:
1 | type profile struct { |
校验函数改为:
1 | import "gopkg.in/go-playground/validator.v10" |
可以看到,gopkg.in/go-playground/validator.v10
虽然减少了部分代码,但是校验逻辑需要写在结构体的的标签上面,增加了代码耦合。另外,validator
还不支持枚举的校验。
使用checker
本文介绍的checker由Rule
和Checker
组成,在外部对结构体的每一个字段添加规则,降低代码耦合性,并且提供组合规则,枚举等规则,可以轻松实现不同规则的自由组合。
1 | func getProfileChecker() checker.Checker { |
通过的checker
的自由搭配,TestProfileCheckerPassed函数无需添加额外的代码,即可完成校验,降低了代码耦合性。校验的逻辑都在checker
里面,校验逻辑更为清晰。
参考文档
我的公众号:lyp分享的地方
我的知乎专栏: https://zhuanlan.zhihu.com/c_1275466546035740672
我的博客:www.liangyaopei.com
Github Page: https://liangyaopei.github.io/