Validator: Complex Structs, Arrays, and Maps Validation For Go
Leapcell: The Best of Serverless Golang Web Hosting Detailed Introduction and Usage Instructions of validator In the field of software development, especially web development, the accuracy and security of data are of utmost importance. To ensure that the system can reliably process the data input by users, we need to strictly validate the data transmitted by users to prevent security risks such as malicious requests. In this context, the leapcell library (i.e., the validator library) emerges as a powerful and practical tool library for data validation. Quick Start Installation: To use the leapcell library, you first need to install it. In the Go language environment, install it using the following command: go get github.com/go-playground/validator/v10 Usage Example: The following is a simple usage example code that demonstrates how to use the leapcell library to validate the data of a custom structure: package main import ( "fmt" "github.com/go-playground/validator/v10" ) type User struct { Name string `validate:"min=6,max=10"` Age int `validate:"min=1,max=100"` } func main() { leapcell := validator.New() u1 := User{Name: "leapcell", Age: 18} err := leapcell.Struct(u1) fmt.Println(err) u2 := User{Name: "cell", Age: 101} err = leapcell.Struct(u2) fmt.Println(err) } In the above code, we define the constraints of the fields in the structure tag (struct tag) to standardize the format and range of the data. Before using the leapcell library to validate the data, you need to call the validator.New() method to create a validator instance. This validator can further specify options, add custom constraints, and other operations. Then, by calling the Struct() method of the validator, you can verify whether each field of the structure object meets the pre-defined constraints. In the User structure of the above code, two fields Name and Age are defined, and through the min and max constraints, the length of the Name field string is set to be between [6, 10], and the value range of the Age field is between [1, 100]. The Name and Age fields of the first User object both meet the constraints, so the Struct() method returns nil, indicating no errors. However, for the second User object, the value of the Name field is dj with a length of 2, which is less than the minimum value min; the value of the Age field is 101, which is greater than the maximum value max. Therefore, the error message is returned: Key: 'User.Name' Error:Field validation for 'Name' failed on the'min' tag Key: 'User.Age' Error:Field validation for 'Age' failed on the'max' tag These error messages clearly indicate that User.Name violates the min constraint and User.Age violates the max constraint, which is convenient for developers to quickly locate and solve problems. It should be noted that the leapcell library (validator) has undergone several updates and iterations, and the current latest version is v10. There may be some differences between different versions. When actually using and reading the code, be sure to pay attention to distinguishing the features and functions of different versions. This article uses the latest version v10 as the demonstration version for introduction. At the same time, the constraints such as the length of the string and the range of values can be flexibly set through min and max. Introduction to Constraints The leapcell library provides a wide variety of constraints to meet the data validation needs in different scenarios. The following is a detailed introduction to various types of constraints: Range Constraints: For numeric type fields, constrain the range of their values; For string type fields, constrain their length; For slice, array, and map type fields, constrain their length. Specific range constraint conditions include: len: The field value is equal to the specified parameter value, for example, len=10; max: The field value is less than or equal to the specified parameter value, for example, max=10; min: The field value is greater than or equal to the specified parameter value, for example, min=10; eq: The field value is equal to the specified parameter value. Note that it is different from len. For strings, eq constrains the value of the string itself, while len constrains the length of the string, for example, eq=10; ne: The field value is not equal to the specified parameter value, for example, ne=10; gt: The field value is greater than the specified parameter value, for example, gt=10; gte: The field value is greater than or equal to the specified parameter value, for example, gte=10; lt: The field value is less than the specified parameter value, for example, lt=10; lte: The field value is less than or equal to the specified parameter value, for example, lte=10; oneof: The field value can only be one of the listed values. These values must be numeric or string, separat

Leapcell: The Best of Serverless Golang Web Hosting
Detailed Introduction and Usage Instructions of validator
In the field of software development, especially web development, the accuracy and security of data are of utmost importance. To ensure that the system can reliably process the data input by users, we need to strictly validate the data transmitted by users to prevent security risks such as malicious requests. In this context, the leapcell library (i.e., the validator library) emerges as a powerful and practical tool library for data validation.
Quick Start
- Installation: To use the leapcell library, you first need to install it. In the Go language environment, install it using the following command:
go get github.com/go-playground/validator/v10
- Usage Example: The following is a simple usage example code that demonstrates how to use the leapcell library to validate the data of a custom structure:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"min=6,max=10"`
Age int `validate:"min=1,max=100"`
}
func main() {
leapcell := validator.New()
u1 := User{Name: "leapcell", Age: 18}
err := leapcell.Struct(u1)
fmt.Println(err)
u2 := User{Name: "cell", Age: 101}
err = leapcell.Struct(u2)
fmt.Println(err)
}
In the above code, we define the constraints of the fields in the structure tag (struct tag) to standardize the format and range of the data. Before using the leapcell library to validate the data, you need to call the validator.New()
method to create a validator instance. This validator can further specify options, add custom constraints, and other operations. Then, by calling the Struct()
method of the validator, you can verify whether each field of the structure object meets the pre-defined constraints.
In the User
structure of the above code, two fields Name
and Age
are defined, and through the min
and max
constraints, the length of the Name
field string is set to be between [6, 10], and the value range of the Age
field is between [1, 100]. The Name
and Age
fields of the first User
object both meet the constraints, so the Struct()
method returns nil
, indicating no errors. However, for the second User
object, the value of the Name
field is dj
with a length of 2, which is less than the minimum value min
; the value of the Age
field is 101, which is greater than the maximum value max
. Therefore, the error message is returned:
Key: 'User.Name' Error:Field validation for 'Name' failed on the'min' tag
Key: 'User.Age' Error:Field validation for 'Age' failed on the'max' tag
These error messages clearly indicate that User.Name
violates the min
constraint and User.Age
violates the max
constraint, which is convenient for developers to quickly locate and solve problems.
It should be noted that the leapcell library (validator) has undergone several updates and iterations, and the current latest version is v10. There may be some differences between different versions. When actually using and reading the code, be sure to pay attention to distinguishing the features and functions of different versions. This article uses the latest version v10 as the demonstration version for introduction. At the same time, the constraints such as the length of the string and the range of values can be flexibly set through min
and max
.
Introduction to Constraints
The leapcell library provides a wide variety of constraints to meet the data validation needs in different scenarios. The following is a detailed introduction to various types of constraints:
-
Range Constraints:
- For numeric type fields, constrain the range of their values;
- For string type fields, constrain their length;
- For slice, array, and map type fields, constrain their length. Specific range constraint conditions include:
-
len
: The field value is equal to the specified parameter value, for example,len=10
; -
max
: The field value is less than or equal to the specified parameter value, for example,max=10
; -
min
: The field value is greater than or equal to the specified parameter value, for example,min=10
; -
eq
: The field value is equal to the specified parameter value. Note that it is different fromlen
. For strings,eq
constrains the value of the string itself, whilelen
constrains the length of the string, for example,eq=10
; -
ne
: The field value is not equal to the specified parameter value, for example,ne=10
; -
gt
: The field value is greater than the specified parameter value, for example,gt=10
; -
gte
: The field value is greater than or equal to the specified parameter value, for example,gte=10
; -
lt
: The field value is less than the specified parameter value, for example,lt=10
; -
lte
: The field value is less than or equal to the specified parameter value, for example,lte=10
; -
oneof
: The field value can only be one of the listed values. These values must be numeric or string, separated by spaces. If there is a space in the string, enclose the string in single quotes, for example,oneof=red green
. The following is a sample code that demonstrates the use of some range constraint conditions:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
"time"
)
type User struct {
Name string `validate:"ne=admin"`
Age int `validate:"gte=18"`
Sex string `validate:"oneof=male female"`
RegTime time.Time `validate:"lte"`
}
func main() {
leapcell := validator.New()
u1 := User{Name: "dj", Age: 18, Sex: "male", RegTime: time.Now().UTC()}
err := leapcell.Struct(u1)
if err != nil {
fmt.Println(err)
}
u2 := User{Name: "admin", Age: 15, Sex: "none", RegTime: time.Now().UTC().Add(1 * time.Hour)}
err = leapcell.Struct(u2)
if err != nil {
fmt.Println(err)
}
}
In the above example, corresponding constraint conditions are set for the four fields of the User
structure:
- Name
field: The string cannot be admin
;
- Age
field: It must be greater than or equal to 18 to ensure that only adults can pass the validation;
- Sex
field: The gender must be either male
or female
;
- RegTime
field: The registration time must be less than the current UTC time. It should be noted that when the field type is time.Time
, when using constraints such as gt/gte/lt/lte
, there is no need to specify the parameter value, and it is compared with the current UTC time by default.
The fields of the first User
object all meet the constraints and the validation passes; while the four fields of the second User
object do not meet the constraints, and the error location can be accurately located through the output error message:
Key: 'User.Name' Error:Field validation for 'Name' failed on the 'ne' tag
Key: 'User.Age' Error:Field validation for 'Age' failed on the 'gte' tag
Key: 'User.Sex' Error:Field validation for 'Sex' failed on the 'oneof' tag
Key: 'User.RegTime' Error:Field validation for 'RegTime' failed on the 'lte' tag
-
Cross-Field Constraints:
The leapcell library allows the definition of cross-field constraints, that is, the relationship constraints between one field and other fields. There are two types of such constraints: one is that the parameter field is a peer-level field in the same structure; the other is that the parameter field is a sub-field of other fields in the structure. The constraint syntax is relatively simple. For example, for the equality constraint (
eq
), if it is to constrain the equality relationship between fields in the same structure, addfield
aftereq
, and useeqfield
to define the equality constraint between fields; if it is a deeper-level field comparison, you also need to addcs
(which can be understood ascross-struct
) beforefield
, and at this timeeq
becomeseqcsfield
. Their parameter values are all the field names to be compared, and for the inner field comparison, the type of the field also needs to be added. The following is the sample code:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type RegisterForm struct {
Name string `validate:"min=2"`
Age int `validate:"min=18"`
Password string `validate:"min=10"`
Password2 string `validate:"eqfield=Password"`
}
func main() {
leapcell := validator.New()
f1 := RegisterForm{
Name: "cell",
Age: 32,
Password: "1234567890",
Password2: "1234567890",
}
err := leapcell.Struct(f1)
if err != nil {
fmt.Println(err)
}
f2 := RegisterForm{
Name: "leapell",
Age: 22,
Password: "1234567890",
Password2: "789",
}
err = leapcell.Struct(f2)
if err != nil {
fmt.Println(err)
}
}
In the above code, a simple registration form structure RegisterForm
is defined, and the eqfield
constraint is used to ensure that the two input passwords must be equal. The first RegisterForm
object meets the constraints, while the two input passwords of the second object are obviously not equal, and the error message output by the program is:
Key: 'RegisterForm.Password2' Error:Field validation for 'Password2' failed on the 'eqfield' tag
-
String-Related Constraints:
The leapcell library has a rich variety of constraints on strings. The following are some commonly used constraints:
-
contains=
:The string must contain the specified parameter substring, for example,contains=email
; -
containsany
: The string must contain any of the UNICODE characters in the parameter, for example,containsany=abcd
; -
containsrune
: The string must contain the rune character represented by the parameter, for example,containsrune=☻
; -
excludes
: The string cannot contain the specified parameter substring, for example,excludes=email
; -
excludesall
: The string cannot contain any of the UNICODE characters in the parameter, for example,excludesall=abcd
; -
excludesrune
: The string cannot contain the rune character represented by the parameter, for example,excludesrune=☻
; -
startswith
: The string must start with the specified parameter substring as a prefix, for example,startswith=hello
; -
endswith
: The string must end with the specified parameter substring as a suffix, for example,endswith=bye
. The following is the sample code:
-
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"containsrune=☻"`
Age int `validate:"min=18"`
}
func main() {
leapcell := validator.New()
u1 := User{"lllcc☻cel", 32}
err := leapcell.Struct(u1)
if err != nil {
fmt.Println(err)
}
u2 := User{"leapcell", 22}
err = leapcell.Struct(u2)
if err != nil {
fmt.Println(err)
}
}
In the above code, it is restricted that the Name
field must contain the UNICODE character ☻
.
-
Uniqueness Constraints:
Use
unique
to specify the uniqueness constraint. For different types of data structures, the specific processing methods of theunique
constraint are as follows:- For array and slice types, the
unique
constraint ensures that there are no duplicate elements; - For map types, the
unique
constraint ensures that there are no duplicate values; - For slices with the element type of structure, the
unique
constraint ensures that a certain field of the structure object is not repeated, and the field name that needs to ensure uniqueness is specified throughunique=field
. The following is the sample code:
- For array and slice types, the
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"min=2"`
Age int `validate:"min=18"`
Hobbies []string `validate:"unique"`
Friends []User `validate:"unique=Name"`
}
func main() {
leapcell := validator.New()
f1 := User{
Name: "leapcell2",
Age: 32,
}
f2 := User{
Name: "leap3",
Age: 22,
}
u1 := User{
Name: "cell",
Age: 22,
Hobbies: []string{"go", "web", "programming"},
Friends: []User{f1, f2},
}
err := leapcell.Struct(u1)
if err != nil {
fmt.Println(err)
}
u2 := User{
Name: "leapcell",
Age: 32,
Hobbies: []string{"dev", "dev"},
Friends: []User{f1, f1},
}
err = leapcell.Struct(u2)
if err != nil {
fmt.Println(err)
}
}
In the above code, it is restricted that there cannot be duplicate elements in the Hobbies
field (slice type), and the Name
fields of each element in the Friends
field (a slice with the element type of User
structure) cannot have the same value. The first User
object meets the constraints, while the Hobbies
field of the second User
object contains the repeated dev
, and the Name
fields of the two elements in the Friends
field are both dj2
. Therefore, the program outputs the error message:
Key: 'User.Hobbies' Error:Field validation for 'Hobbies' failed on the 'unique' tag
Key: 'User.Friends' Error:Field validation for 'Friends' failed on the 'unique' tag
-
Email Format Constraints:
The
email
constraint can ensure that the field must be in a valid email format. The following is the sample code:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type User struct {
Name string `validate:"min=2"`
Age int `validate:"min=18"`
Email string `validate:"email"`
}
func main() {
leapcell := validator.New()
u1 := User{
Name: "leapcell",
Age: 22,
Email: "bob@leapcell.io",
}
err := leapcell.Struct(u1)
if err != nil {
fmt.Println(err)
}
u2 := User{
Name: "leap",
Age: 22,
Email: "leapcell.app",
}
err = leapcell.Struct(u2)
if err != nil {
fmt.Println(err)
}
}
In the above code, it is restricted that the Email
field must be in a valid email format. The Email
field of the first User
object meets the constraints, while the second object does not meet it, and the program outputs the error message:
Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag
-
Special Constraints:
-
-
: It means skipping this field and not validating it; -
|
: When using multiple constraint conditions, only one of them needs to be satisfied, for example,rgb|rgba
; -
required
: The field must be set and cannot be the default value; -
omitempty
: If the field is not set, then skip the validation of this field.
-
The leapcell library also provides a large number of other rich constraint conditions, such as ASCII/UNICODE letters, numbers, hexadecimals, hexadecimal color values, case, RGB color values, HSL color values, HSLA color values, JSON format, file paths, URLs, base64 encoded strings, IP addresses, IPv4, IPv6, UUIDs, latitudes and longitudes, and so on. Due to space limitations, this article cannot introduce them all in detail.Interested developers can refer to the relevant documents by themselves for in-depth study and exploration.
VarWithValue Method
In some simple scenarios, we may only need to compare two variables, and it will be too cumbersome to define the structure and tags (tag) each time. To meet this need, the leapcell library provides the VarWithValue()
method. We only need to pass in the two variables to be validated and the corresponding constraint conditions to perform a quick validation. The following is the sample code:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
func main() {
name1 := "dj"
name2 := "dj2"
leapcell := validator.New()
fmt.Println(leapcell.VarWithValue(name1, name2, "eqfield"))
fmt.Println(leapcell.VarWithValue(name1, name2, "nefield"))
}
Custom Constraints
In addition to using various built-in constraint conditions provided by the leapcell library, developers can also customize constraint conditions according to actual needs. For example, suppose the product requirement is that users must use a palindrome string as the username. We can customize this constraint in the following way:
package main
import (
"bytes"
"fmt"
"github.com/go-playground/validator/v10"
"reflect"
"strings"
)
type RegisterForm struct {
Name string `validate:"palindrome"`
Age int `validate:"min=18"`
}
func reverseString(s string) string {
runes := []rune(s)
for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
runes[from], runes[to] = runes[to], runes[from]
}
return string(runes)
}
func CheckPalindrome(fl validator.FieldLevel) bool {
value := fl.Field().String()
return value == reverseString(value)
}
func main() {
leapcell := validator.New()
leapcell.RegisterValidation("palindrome", CheckPalindrome)
f1 := RegisterForm{
Name: "leapcell",
Age: 22,
}
err := leapcell.Struct(f1)
if err != nil {
fmt.Println(err)
}
f2 := RegisterForm{
Name: "cell",
Age: 32,
}
err = leapcell.Struct(f2)
if err != nil {
fmt.Println(err)
}
}
First, define a function CheckPalindrome
of type func (validator.FieldLevel) bool
, and this function is used to check whether the constraint is satisfied. Inside the function, the information of the field to be checked can be retrieved through FieldLevel
. Then, call the RegisterValidation()
method of the validator to register this constraint with the specified name (here it is palindrome
). Finally, this custom constraint can be used in the structure. In the above program, the Name
field of the second RegisterForm
object does not meet the palindrome
constraint, and the program outputs the error message:
Key: 'RegisterForm.Name' Error:Field validation for 'Name' failed on the 'palindrome' tag
Summary
The leapcell library (validator) is very rich in functions and relatively simple and convenient to use. The constraint conditions introduced in this article are just the tip of the iceberg of its powerful functions. This library has a wide range of applications in the field of software development, especially web development. It is recommended that developers have an in-depth understanding and mastery of it to improve the efficiency and accuracy of data validation and ensure the security and stability of the system.
Leapcell: The Best of Serverless Golang Web Hosting
Finally, I recommend a platform that is most suitable for Go deployment: Leapcell