Валидация
Go-библиотека для валидации и фильтрации данных, простая в использовании, со встроенным большинством часто используемых валидаторов и фильтров, с поддержкой пользовательских сообщений и перевода полей.
Проект вдохновлён такими проектами, как albrow/forms, asaskevich/govalidator и inhere/php-validate. Авторы выражают им свою благодарность.
Пожалуйста, ознакомьтесь с введением на английском языке README.
Добавьте тег validate к структуре, чтобы быстро настроить валидацию для этой структуры.
Можно комбинировать теги message и label для быстрой настройки перевода полей структуры и сообщений об ошибках.
Пример кода:
package main
import (
"fmt"
"time"
"github.com/gookit/validate"
)
// UserForm struct
type UserForm struct {
Name string `validate:"required|min_len:7" message:"required:{field} is required" label:"用户名称"`
Email string `validate:"email" message:"email is invalid" label:"用户邮箱"`
Age int `validate:"required|int|min:1|max:99" message:"int:age must int|min:age min value is 1"`
CreateAt int `validate:"min:1"`
Safe int `validate:"-"` // 标记字段安全无需验证
UpdateAt time.Time `validate:"required" message:"update time is required"`
Code string `validate:"customValidator"`
// 结构体嵌套
ExtInfo struct{
Homepage string `validate:"required" label:"用户主页"`
CityName string
} `validate:"required" label:"扩展信息"`
}
// CustomValidator custom validator in the source struct.
func (f UserForm) CustomValidator(val string) bool {
return len(val) == 4
}
Структуры могут реализовывать три метода интерфейса для дополнительной настройки:
Пример кода:
package main
import (
"fmt"
"time"
"github.com/gookit/validate"
)
// UserForm struct
type UserForm struct {
Name string `validate:"required|minLen:7"`
Email string `validate:"email"`
Age int `validate:"required|int|min:1|max:99"`
Safe int `validate:"-"`
CreateAt int `validate:"min:1"`
UpdateAt time.Time `validate:"required"`
Code string `validate:"customValidator"` // 使用自定义验证器
// 结构体嵌套
ExtInfo struct{
Homepage string `validate:"required"`
CityName string
} `validate:"required"`
}
// CustomValidator 定义在结构体中的自定义验证器
func (f UserForm) CustomValidator(val string) bool {
...
} ```
return len(val) == 4
}
// ConfigValidation 配置验证
// - 定义验证场景
// - 也可以添加验证设置
func (f UserForm) ConfigValidation(v *validate.Validation) {
// v.StringRule()
v.WithScenes(validate.SValues{
"add": []string{"ExtInfo.Homepage", "Name", "Code"},
"update": []string{"ExtInfo.CityName", "Name"},
})
}
// Messages 您可以自定义验证器错误消息
func (f UserForm) Messages() map[string]string {
return validate.MS{
"required": "oh! the {field} is required",
"Name.required": "message for special field",
}
}
// Translates 你可以自定义字段翻译
func (f UserForm) Translates() map[string]string {
return validate.MS{
"Name": "用户名称",
"Email": "用户邮箱",
"ExtInfo.Homepage": "用户主页",
}
}```
### Создание и вызов проверки
```go
func main() {
u := &UserForm{
Name: "inhere",
}
// 创建 Validation 实例
v := validate.Struct(u)
// 或者使用
// v := validate.New(u)
if v.Validate() { // 验证成功
// do something ...
} else {
fmt.Println(v.Errors) // 所有的错误消息
fmt.Println(v.Errors.One()) // 返回随机一条错误消息
fmt.Println(v.Errors.Field("Name")) // 返回该字段的错误消息
}
}
Map
данныхpackage main
import "fmt"
import "github.com/gookit/validate"
func main() {
m := map[string]interface{}{
"name": "inhere",
"age": 100,
"oldSt": 1,
"newSt": 2,
"email": "some@email.com",
}
v := validate.Map(m)
// v := validate.New(m)
v.AddRule("name", "required")
v.AddRule("name", "minLen", 7)
v.AddRule("age", "max", 99)
v.AddRule("age", "min", 1)
v.AddRule("email", "email")
// 也可以这样,一次添加多个验证器
v.StringRule("age", "required|int|min:1|max:99")
v.StringRule("name", "required|minLen:7")
// feat: 支持在 slice 中检查子项的值
v.StringRule("tags.*", "required|string|min_len:7")
// 设置不同场景验证不同的字段
// v.WithScenes(map[string]string{
// "create": []string{"name", "email"},
// "update": []string{"name"},
// })
if v.Validate() { // validate ok
// do something ...
} else {
fmt.Println(v.Errors) // all error messages
fmt.Println(v.Errors.One()) // returns a random error message text
}
}
Передать в *http.Request
, быстрый метод FromRequest()
автоматически соберёт соответствующие данные на основе метода запроса и типа данных запроса.
GET/DELETE/...
и т. д., будет собирать данные URL queryPOST/PUT/PATCH
и тип application/json
будет собирать данные JSONPOST/PUT/PATCH
и тип multipart/form-data
будет собирать данные формы, а также данные загрузки файловPOST/PUT/PATCH
и тип application/x-www-form-urlencoded
будет собирать данные формыpackage main
import (
"fmt"
"net/http"
"github.com/gookit/validate"
)
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := validate.FromRequest(r)
if err != nil {
panic(err)
}
v := data.Create()
// setting rules
v.FilterRule("age", "int") // convert value to int
v.AddRule("name", "required")
v.AddRule("name", "minLen", 7)
v.AddRule("age", "max", 99)
if v.Validate() { // validate ok
// do something ...
} else {
fmt.Println(v.Errors) // all error messages
fmt.Println(v.Errors.One()) // returns a random error message text
}
})
http.ListenAndServe(":8090", handler)
}
Быстро создать экземпляр Validation
:
Request(r *http.Request) *Validation
JSON(s string, scene ...string) *Validation
Struct(s interface{}, scene ...string) *Validation
Map(m map[string]interface{}, scene ...string) *Validation
New(data interface{}, scene ...string) *Validation
Быстро создайте экземпляр DataFace
:
FromMap(m map[string]interface{}) *MapData
FromStruct(s interface{}) (*StructData, error)
FromJSON(s string) (*MapData, error)
FromJSONBytes(bs []byte) (*MapData, error)
FromURLValues(values url.Values) *FormData
FromRequest(r *http.Request, maxMemoryLimit ...int64) (DataFace, error)
Проверка (Validation) в Go: методы, ошибки и глобальные настройки
Методы:
Ошибки: v.Errors — это карта данных, где ключ — это имя поля, а значение — map[string]string.
Пример проверки:
// do validating
if v.Validate() {
return nil
}
// get errors
es := v.Errors
// check
es.Empty() // bool
// возвращает случайную ошибку, если ошибок нет, то возвращает nil
fmt.Println(v.Errors.OneError())
fmt.Println(v.Errors.ErrOrNil())
fmt.Println(v.Errors) // все сообщения об ошибках
fmt.Println(v.Errors.One()) // возвращает случайное сообщение об ошибке
fmt.Println(v.Errors.Field("Name")) // возвращает сообщения об ошибках для поля
JSON-ошибки:
{
"field1": {
"required": "error msg0"
}
}
{
"field1": {
"minLen": "error msg1",
"required": "error msg0"
},
"field2": {
"min": "error msg2"
}
}
Глобальные опции: Вы можете изменить логику обработки валидатора, изменив глобальные параметры.
// GlobalOption settings for validate
type GlobalOption struct {
// FilterTag 结构体中的过滤规则标签名称。默认 'filter`
FilterTag string
// ValidateTag 结构体中的验证规则标签名称。默认 'validate`
ValidateTag string
// FieldTag 定义结构体字段验证错误时的输出名字。默认使用 json
FieldTag string
// LabelTag 定义структура поля проверки ошибок времени перевода имени。默认使用 label
// - 等同于设置 字段 translate
LabelTag string
// MessageTag define error message for the field. default: message
MessageTag string
// StopOnError 如果为 true,则出现第一个错误时,将停止继续验证。默认 true
StopOnError bool
// SkipOnEmpty 跳过对字段不存在或值为空的检查。默认 true
SkipOnEmpty bool
// UpdateSource Whether to update source field value, useful for struct validate
UpdateSource bool
// CheckDefault Whether to validate the default value set by the user
CheckDefault bool
// CheckZero Whether validate the default zero value. (intX,uintX: 0, string: "")
CheckZero bool
// CheckSubOnParentMarked 当字段是一个结构体时,仅在当前字段配置了验证tag时才收集子结构体的规则
CheckSubOnParentMarked bool
}
Настройка:
// 更改全局选项
validate.Config(func(opt *validate.GlobalOption) {
opt.StopOnError = false
opt.SkipOnEmpty = false
})
Пользовательские сообщения об ошибках:
import "github.com/gookit/validate/locales/zhcn"
// for all Validation.
// NOTICE: 必须在调用 validate.New() 前注册, 它只需要一次调用。
zhcn.RegisterGlobal()
// ... ...
v := validate.New()
// only for current Validation
zhcn.Register(v)
validate.AddGlobalMessages(map[string]string{
"minLength": "OO! {field} min length is %d",
})
v := validate.New(map[string]interface{}{
"name": "inhere",
})
v.StringRule("name", "required|string|minLen:7|maxLen:15")
v.AddMessages(map[string]string{
"minLength": "OO! {field} min length is %d",
"name.minLen": "OO! username min length is %d",
})
message, label
:type UserForm struct {
Name string `validate:"required|minLen:7" label:"用户名称"`
Email string `validate:"email" message:"email is invalid" label:"用户邮箱"`
}
Messages()
для добавления:// Messages you can custom validator error messages.
func (f UserForm) Messages() map[string]string {
return validate.MS{
"required": "oh! the {field} is required",
"Name.required": "message for special field",
}
}
Создание пользовательских валидаторов:
validate
поддерживает добавление пользовательских валидаторов, и поддерживает добавление глобальных и временных валидаторов.
В структуре можно добавить метод проверки. Пример использования см. в примере структуры выше func (f UserForm) CustomValidator(val string) bool
.
Обратите внимание: метод валидатора должен возвращать логическое значение, указывающее на успешность валидации. Первый параметр — это соответствующее значение поля, дополнительные параметры добавляются автоматически. ``` myCheck1: func(val interface{}) bool { // do validate val ... return true }, )
#### Добавление временных валидаторов
Также можно добавить один или несколько пользовательских валидаторов за один раз.
```go
v := validate.Struct(u)
v.AddValidator("myFunc3", func(val interface{}) bool {
// do validate val ...
return true
})
v.AddValidators(M{
"myFunc4": func(val interface{}) bool {
// do validate val ...
return true
},
})
validate
также позволяет добавлять пользовательские фильтры, поддерживая как глобальные, так и временные фильтры двух типов.
TIP: Для функций фильтра допускается наличие одного возвращаемого значения
inteface{}
или двух возвращаемых значений(inteface{},error)
, где второе может возвращать ошибку.
Можно добавить один или несколько глобальных фильтров за один раз.
package main
import "github.com/gookit/validate"
func init() {
validate.AddFilter("myToIntFilter0", func(val interface{}) int {
// do filtering val ...
return 1
})
validate.AddFilters(validate.M{
"myToIntFilter1": func(val interface{}) (int, error) {
// do filtering val ...
return 1, nil
},
})
}
Аналогично можно добавить один или несколько временных фильтров за один раз.
package main
import "github.com/gookit/validate"
func main() {
v := validate.New(&someStrcut{})
v.AddFilter("myToIntFilter0", func(val interface{}) int {
// do filtering val ...
return 1
})
v.AddFilters(validate.M{
"myToIntFilter1": func(val interface{}) (int, error) {
// do filtering val ...
return 1, nil
},
})
}
Позволяет создавать пользовательские валидаторы required для индивидуальной проверки на пустоту. Однако следует отметить, что имя валидатора должно начинаться с required, например required_custom.
type Data struct {
Age int `validate:"required_custom" message:"age is required"`
Name string `validate:"required"`
}
v := validate.New(&Data{
Name: "tom",
Age: 0,
})
v.AddValidator("required_custom", func(val interface{}) bool {
// do check value
return false
})
ok := v.Validate()
assert.False(t, ok)
В любом фреймворке можно использовать validate
, включая Gin, Echo, Chi и другие. Здесь приведён пример использования с Gin.
package main
import (
"github.com/gin-gonic/gin/binding"
"github.com/gookit/validate"
)
// implements the binding.StructValidator
type customValidator struct {}
func (c *customValidator) ValidateStruct(ptr interface{}) error {
v := validate.Struct(ptr)
v.Validate() // 调用验证
return v.Errors
}
func (c *customValidator) Engine() interface{} {
return nil
}
func main() {
// ...
// after init gin, set custom validator
binding.Validator = &customValidator{}
}
Несколько основных категорий:
TIP: Все верблюжьи имена валидаторов теперь имеют добавленные псевдонимы в нижнем регистре. Таким образом, endsWith также можно записать как ends_with.
Валидатор/псевдоним | Описание |
---|---|
required | Поле обязательно, значение не может быть пустым |
required_if/requiredIf | required_if:anotherfield,value,... Если другое поле anotherField имеет любое из значений value, то это поле проверки должно существовать и не быть пустым. |
required_unless/requiredUnless | required_unless:anotherfield,value,... Если другое поле не равно любому из значений, то это поле проверки должно существовать и не быть пустым. |
required_with/requiredWith | required_with:foo,bar,... Только когда другие указанные поля присутствуют, поле проверки должно существовать и быть непустым. |
required_with_all/requiredWithAll | required_with_all:foo,bar,... Поле проверки должно существовать и быть непустым только тогда, когда все указанные поля присутствуют. |
required_without/requiredWithout | required_without:foo,bar,... Когда другие указанные поля отсутствуют, поле проверки должно существовать и быть непустым. |
required_without_all/requiredWithoutAll | required_without_all:foo,bar,... Поле проверки должно существовать и быть непустым, только когда все указанные поля отсутствуют. |
-/safe | Помечает текущее поле как безопасное, без необходимости проверки |
int/integer/isInt | Проверяет, является ли значение intX или uintX, одновременно поддерживая проверку размера "int" "int:2" "int:2,12"
|
uint/isUint | Проверяет, является ли значение uintX (значение >= 0). |
bool/isBool | Проверяет, является ли значение булевой строкой (true : "1", "on", "yes", "true", false : "0", "off", "no", "false"). |
string/isString | Проверяет, является ли значение строковым, одновременно поддерживая длину проверки "string" "string:2" "string:2,12"
|
float/isFloat | Проверяет, является ли значение float(floatX ) |
slice/isSlice | Проверяет, является ли значение slice ([]intX []uintX []byte []string и т.д.). |
in/enum | Проверяет, находится ли значение в заданном списке перечислений ([]string , []intX , []uintX ) Инструменты Gookit
|
off, no, false)
trim/trimSpace
| Очистить строку от пробельных символов с обеих сторон
ltrim/trimLeft
| Очистить строку от пробельных символов слева
rtrim/trimRight
| Очистить строку от пробельных символов справа
int/integer
| Преобразовать значение (строка / intX / floatX) в тип int v.FilterRule("id", "int")
lower/lowercase
| Перевести строку в нижний регистр
upper/uppercase
| Перевести строку в верхний регистр
lcFirst/lowerFirst
| Сделать первый символ строки строчным
ucFirst/upperFirst
| Сделать первый символ строки прописным
ucWord/upperWord
| Сделать первые символы слов прописными
camel/camelCase
| Привести строку к стилю именования Camel
snake/snakeCase
| Привести строку к стилю именования Snake
escapeJs/escapeJS
| Экранировать строку JS
escapeHtml/escapeHTML
| Экранировать HTML-строку
str2ints/strToInts
| Конвертировать строку в срез int []int
str2time/strToTime
| Конвертировать дату в строку формата time.Time
str2arr/str2array/strToArray
| Конвертировать строку в массив строк []string
Gookit предоставляет набор инструментов для разработки на Go. Вот некоторые из них:
Для получения дополнительной информации посетите страницу https://github.com/gookit.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )