網站首頁 編程語言 正文
前言
對于HTTP請求,我們要在腦子里有一個根深蒂固的概念,那就是任何客戶端傳過來的數據都是不可信任的。那么開發接口的時候需要對客戶端傳提交的參數進行參數校驗,如果提交的參數只有一個兩個,這樣我們可以簡單寫個if判斷,那么要是有很多的參數校驗,那么滿屏都是參數校驗的if判斷,效率不僅低還不美觀,接下來我們介紹一個參數校驗器validator
。
什么是validator
Validator
是一個 Golang 的第三方庫,用于對數據進行校驗,常用于 API 的開發中,對客戶端發出的請求數據進行嚴格校驗,防止惡意請求。
安裝
validator包安裝:
go get -u github.com/go-playground/validator/v10
使用方法
導入validator:
import "github.com/go-playground/validator/v10"
validator 應用了 Golang
的 Struct Tag
和 Reflect
機制,基本思想是:在 Struct Tag
中為不同的字段定義各自類型的約束,然后通過 Reflect
獲取這些約束的類型信息并在校驗器中進行數據校驗。
示例:
package main import ( "fmt" "github.com/go-playground/validator/v10" ) type User struct { UserName string `json:"user_name" validate:"required"` Password string `json:"password" validate:"required,min=6,max=20"` } func main() { example := User{ Password: "123", } //實例化驗證器 validate := validator.New() errs := validate.Struct(example) if errs != nil { for _, err := range errs.(validator.ValidationErrors) { fmt.Println(err) } } }
validator包的驗證提示默認是英文的,輸出如下:
這樣看可能不太清楚,如果需要翻譯成中文則還需安裝驗證提示翻譯包:
go get -u github.com/go-playground/locales go get -u github.com/go-playground/universal-translator
修改后如下:
package main import ( "fmt" "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" zh_translations "github.com/go-playground/validator/v10/translations/zh" ) type User struct { UserName string `json:"user_name" validate:"required"` Password string `json:"password" validate:"required,min=6,max=20"` } func main() { example := User{ Password: "123", } // 中文翻譯器 uni := ut.New(zh.New()) trans, _ := uni.GetTranslator("zh") //實例化驗證器 validate := validator.New() // 注冊翻譯器到校驗器 err := zh_translations.RegisterDefaultTranslations(validate, trans) if err!=nil { fmt.Println(err) return } errs := validate.Struct(example) if errs != nil { for _, err := range errs.(validator.ValidationErrors) { fmt.Println(err.Translate(trans)) } } }
執行輸出:
校驗規則
下面列舉一部分我們開發中經常用到的驗證規則,詳細驗證規則可以參考文檔:
https://pkg.go.dev/gopkg.in/go-playground/validator.v10
Tag | 說明 | 示例 |
---|---|---|
required | 必填 | Field或Struct validate:"required" |
omitempty | 空時忽略 | Field或Struct validate:"omitempty" |
len | 長度 | Field validate:"len=0" |
eq | 等于 | Field validate:"eq=0" |
gt | 大于 | Field validate:"gt=0" |
gte | 大于等于 | Field validate:"gte=0" |
lt | 小于 | Field validate:"lt=0" |
lte | 小于等于 | Field validate:"lte=0" |
min | 最小值 | Field validate:"min=1" |
max | 最大值 | Field validate:"max=2" |
required_with | 其他字段其中一個不為空且當前字段不為空 | Field validate:"required_with=Field1 Field2" |
required_without | 其他字段其中一個為空且當前字段不為空 | Field `validate:“required_without=Field1 Field2” |
lowercase | 符串值是否只包含小寫字符 | Field validate:"lowercase" |
uppercase | 符串值是否只包含大寫字符 | Field validate:"uppercase" |
字符串值包含一個有效的電子郵件 | Field validate:"email" | |
json | 字符串值是否為有效的JSON | Field validate:"json" |
url | 符串值是否包含有效的url | Field validate:"url" |
uri | 符串值是否包含有效的 uri | Field validate:"uri" |
contains | 字符串值包含子字符串值 | Field validate:"contains=@" |
excludes | 字符串值不包含子字符串值 | 字符串值不包含子字符串值 Field validate:"excludes=@" |
ip | 字符串值是否包含有效的 IP 地址 | Field validate:"ip" |
datetime | 字符串值是否包含有效的日期 | Field validate:"datetime" |
startswith | 字符串以提供的字符串值開始 | Field validate:"startswith=abc" |
endswith | 字符串以提供的字符串值結束 | Field validate:"endswith=abc" |
跨字段驗證
validator 允許定義跨字段驗證,即:驗證某個字段與其他字段之間的關系。這種驗證實際上分為兩種:
- 一種是參數字段就是同一個結構體中的平級字段。
- 另一種是參數字段為結構中其他字段的字段。
驗證語法很簡單,如果是驗證同一個結構中的字段,則在基礎的 Tags 后面添加一個 field 后綴,例如:eqfield 定義字段間的相等(eq)約束。如果是更深層次的字段,在 field 之前還需要加上 cs(Cross-Struct),eq 就變為了 eqcsfield。
- eqfield=Field:必須等于 Field 的值。
- nefield=Field:必須不等于 Field 的值。
- gtfield=Field:必須大于 Field 的值。
- gtefield=Field: 必須大于等于 Field 的值。
- ltfield=Field:必須小于 Field 的值。
- ltefield=Field:必須小于等于 Field 的值。
- eqcsfield=Other.Field:必須等于 struct Other 中 Field 的值。
- necsfield=Other.Field:必須不等于 struct Other 中 Field 的值。
- gtcsfield=Other.Field:必須大于 struct Other 中 Field 的值;
- gtecsfield=Other.Field:必須大于等于 struct Other 中 Field 的值。
- ltcsfield=Other.Field:必須小于 struct Other 中 Field 的值。
- ltecsfield=Other.Field:必須小于等于 struct Other 中 Field 的值。
另外還有幾個常用的 Tag:
- required_with=Field1 Field2:在 Field1 或者 Field2 存在時,必須;
- required_with_all=Field1 Field2:在 Field1 與 Field2 都存在時,必須;
- required_without=Field1 Field2:在 Field1 或者 Field2 不存在時,必須;
- required_without_all=Field1 Field2:在 Field1 與 Field2 都存在時,必須;
錯誤處理
通過看源碼,我們可以看到validator 返回的錯誤有兩種,一種是參數錯誤,一種是校驗錯誤,它們都實現了 error 接口。
- 參數錯誤時,返回 InvalidValidationError 類型;
- 校驗錯誤時,返回 ValidationErrors 類型。ValidationErrors 是一個錯誤切片,保存了每個字段違反的每個約束信息。
所以 validator 校驗返回的結果有 3 種情況:
- nil:沒有錯誤;
- InvalidValidationError:輸入參數錯誤;
- ValidationErrors:字段違反約束。
validator 返回的錯誤有兩種,一種是參數錯誤,一種是校驗錯誤,它們都實現了 error 接口。
參數錯誤時,返回 InvalidValidationError 類型;
校驗錯誤時,返回 ValidationErrors 類型。ValidationErrors 是一個錯誤切片,保存了每個字段違反的每個約束信息。
所以 validator 校驗返回的結果只有 3 種情況:
nil:沒有錯誤;
InvalidValidationError:輸入參數錯誤;
ValidationErrors:字段違反約束。
我們可以在程序中判斷 err != nil
時,可以依次將 err轉換為 InvalidValidationError
和 ValidationErrors
以獲取更詳細的信息:
err := validate.Struct(user) if err != nil { invalid, ok := err.(*validator.InvalidValidationError) if ok { fmt.Println("param error:", invalid) return } validationErrs := err.(validator.ValidationErrors) for _, validationErr := range validationErrs { fmt.Println(validationErr) } }
小結
通過以上的內容我們了解了validator
一些基本的功能和用法,在我們開發中大大提高了開發效率。
validator
功能非常豐富,使用較為簡單方便。它的應用非常廣泛,建議了解一下。
原文鏈接:https://juejin.cn/post/7133399499418337311
相關推薦
- 2022-03-30 Docker?鏡像分層及dockerfile?編寫技巧_docker
- 2022-07-27 P標簽如何取消上下間隔
- 2022-12-25 Python中你所不知道的星號?*?用法_python
- 2022-06-01 AutoMapper實體映射基本用法_實用技巧
- 2022-04-09 SpringBoot自定義validation注解校驗參數只能為指定的值
- 2022-12-13 bat文件與Vbs文件之間的常用操作(獲取用戶輸入,執行VBS文件)_DOS/BAT
- 2023-01-12 python如何批量讀取.mat文件并保存成.npy_python
- 2022-04-12 Oracle?Session每日統計功能實現_oracle
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支