{"id":13367369,"url":"https://github.com/Go-ozzo/ozzo-validation","last_synced_at":"2025-03-12T18:32:34.386Z","repository":{"id":38238005,"uuid":"61687013","full_name":"go-ozzo/ozzo-validation","owner":"go-ozzo","description":"An idiomatic Go (golang) validation package. Supports configurable and extensible validation rules (validators) using normal language constructs instead of error-prone struct tags.","archived":false,"fork":false,"pushed_at":"2024-03-23T08:31:26.000Z","size":213,"stargazers_count":3663,"open_issues_count":52,"forks_count":220,"subscribers_count":29,"default_branch":"master","last_synced_at":"2024-08-11T11:48:41.245Z","etag":null,"topics":["go","golang","ozzo","validation","validator"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-ozzo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-22T03:47:43.000Z","updated_at":"2024-08-10T05:14:41.000Z","dependencies_parsed_at":"2023-02-12T11:48:27.927Z","dependency_job_id":"7023b480-a43b-4782-91c0-eab731d285ba","html_url":"https://github.com/go-ozzo/ozzo-validation","commit_stats":{"total_commits":97,"total_committers":27,"mean_commits":"3.5925925925925926","dds":"0.38144329896907214","last_synced_commit":"34bd5476bd5bb4884aee8252974da4cd4e878a75"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-ozzo%2Fozzo-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-ozzo%2Fozzo-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-ozzo%2Fozzo-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-ozzo%2Fozzo-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-ozzo","download_url":"https://codeload.github.com/go-ozzo/ozzo-validation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221309977,"owners_count":16795837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","ozzo","validation","validator"],"created_at":"2024-07-30T00:01:45.976Z","updated_at":"2024-10-24T11:31:15.557Z","avatar_url":"https://github.com/go-ozzo.png","language":"Go","funding_links":[],"categories":["验证","驗證"],"sub_categories":["高级控制台界面","高級控制台界面"],"readme":"# ozzo-validation\n\n[![GoDoc](https://godoc.org/github.com/go-ozzo/ozzo-validation?status.png)](http://godoc.org/github.com/go-ozzo/ozzo-validation)\n[![Build Status](https://travis-ci.org/go-ozzo/ozzo-validation.svg?branch=master)](https://travis-ci.org/go-ozzo/ozzo-validation)\n[![Coverage Status](https://coveralls.io/repos/github/go-ozzo/ozzo-validation/badge.svg?branch=master)](https://coveralls.io/github/go-ozzo/ozzo-validation?branch=master)\n[![Go Report](https://goreportcard.com/badge/github.com/go-ozzo/ozzo-validation)](https://goreportcard.com/report/github.com/go-ozzo/ozzo-validation)\n\n## Description\n\nozzo-validation is a Go package that provides configurable and extensible data validation capabilities.\nIt has the following features:\n\n* use normal programming constructs rather than error-prone struct tags to specify how data should be validated.\n* can validate data of different types, e.g., structs, strings, byte slices, slices, maps, arrays.\n* can validate custom data types as long as they implement the `Validatable` interface.\n* can validate data types that implement the `sql.Valuer` interface (e.g. `sql.NullString`).\n* customizable and well-formatted validation errors.\n* error code and message translation support.\n* provide a rich set of validation rules right out of box.\n* extremely easy to create and use custom validation rules.\n\nFor an example on how this library is used in an application, please refer to [go-rest-api](https://github.com/qiangxue/go-rest-api) which is a starter kit for building RESTful APIs in Go.\n\n## Requirements\n\nGo 1.13 or above.\n\n\n## Getting Started\n\nThe ozzo-validation package mainly includes a set of validation rules and two validation methods. You use \nvalidation rules to describe how a value should be considered valid, and you call either `validation.Validate()`\nor `validation.ValidateStruct()` to validate the value.\n\n\n### Installation\n\nRun the following command to install the package:\n\n```\ngo get github.com/go-ozzo/ozzo-validation\n```\n\n### Validating a Simple Value\n\nFor a simple value, such as a string or an integer, you may use `validation.Validate()` to validate it. For example, \n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/go-ozzo/ozzo-validation/v4\"\n\t\"github.com/go-ozzo/ozzo-validation/v4/is\"\n)\n\nfunc main() {\n\tdata := \"example\"\n\terr := validation.Validate(data,\n\t\tvalidation.Required,       // not empty\n\t\tvalidation.Length(5, 100), // length between 5 and 100\n\t\tis.URL,                    // is a valid URL\n\t)\n\tfmt.Println(err)\n\t// Output:\n\t// must be a valid URL\n}\n```\n\nThe method `validation.Validate()` will run through the rules in the order that they are listed. If a rule fails\nthe validation, the method will return the corresponding error and skip the rest of the rules. The method will\nreturn nil if the value passes all validation rules.\n\n\n### Validating a Struct\n\nFor a struct value, you usually want to check if its fields are valid. For example, in a RESTful application, you\nmay unmarshal the request payload into a struct and then validate the struct fields. If one or multiple fields\nare invalid, you may want to get an error describing which fields are invalid. You can use `validation.ValidateStruct()`\nto achieve this purpose. A single struct can have rules for multiple fields, and a field can be associated with multiple \nrules. For example,\n\n```go\ntype Address struct {\n\tStreet string\n\tCity   string\n\tState  string\n\tZip    string\n}\n\nfunc (a Address) Validate() error {\n\treturn validation.ValidateStruct(\u0026a,\n\t\t// Street cannot be empty, and the length must between 5 and 50\n\t\tvalidation.Field(\u0026a.Street, validation.Required, validation.Length(5, 50)),\n\t\t// City cannot be empty, and the length must between 5 and 50\n\t\tvalidation.Field(\u0026a.City, validation.Required, validation.Length(5, 50)),\n\t\t// State cannot be empty, and must be a string consisting of two letters in upper case\n\t\tvalidation.Field(\u0026a.State, validation.Required, validation.Match(regexp.MustCompile(\"^[A-Z]{2}$\"))),\n\t\t// State cannot be empty, and must be a string consisting of five digits\n\t\tvalidation.Field(\u0026a.Zip, validation.Required, validation.Match(regexp.MustCompile(\"^[0-9]{5}$\"))),\n\t)\n}\n\na := Address{\n    Street: \"123\",\n    City:   \"Unknown\",\n    State:  \"Virginia\",\n    Zip:    \"12345\",\n}\n\nerr := a.Validate()\nfmt.Println(err)\n// Output:\n// Street: the length must be between 5 and 50; State: must be in a valid format.\n```\n\nNote that when calling `validation.ValidateStruct` to validate a struct, you should pass to the method a pointer \nto the struct instead of the struct itself. Similarly, when calling `validation.Field` to specify the rules\nfor a struct field, you should use a pointer to the struct field. \n\nWhen the struct validation is performed, the fields are validated in the order they are specified in `ValidateStruct`. \nAnd when each field is validated, its rules are also evaluated in the order they are associated with the field.\nIf a rule fails, an error is recorded for that field, and the validation will continue with the next field.\n\n\n### Validating a Map\n\nSometimes you might need to work with dynamic data stored in maps rather than a typed model. You can use `validation.Map()`\nin this situation. A single map can have rules for multiple keys, and a key can be associated with multiple \nrules. For example,\n\n```go\nc := map[string]interface{}{\n\t\"Name\":  \"Qiang Xue\",\n\t\"Email\": \"q\",\n\t\"Address\": map[string]interface{}{\n\t\t\"Street\": \"123\",\n\t\t\"City\":   \"Unknown\",\n\t\t\"State\":  \"Virginia\",\n\t\t\"Zip\":    \"12345\",\n\t},\n}\n\nerr := validation.Validate(c,\n\tvalidation.Map(\n\t\t// Name cannot be empty, and the length must be between 5 and 20.\n\t\tvalidation.Key(\"Name\", validation.Required, validation.Length(5, 20)),\n\t\t// Email cannot be empty and should be in a valid email format.\n\t\tvalidation.Key(\"Email\", validation.Required, is.Email),\n\t\t// Validate Address using its own validation rules\n\t\tvalidation.Key(\"Address\", validation.Map(\n\t\t\t// Street cannot be empty, and the length must between 5 and 50\n\t\t\tvalidation.Key(\"Street\", validation.Required, validation.Length(5, 50)),\n\t\t\t// City cannot be empty, and the length must between 5 and 50\n\t\t\tvalidation.Key(\"City\", validation.Required, validation.Length(5, 50)),\n\t\t\t// State cannot be empty, and must be a string consisting of two letters in upper case\n\t\t\tvalidation.Key(\"State\", validation.Required, validation.Match(regexp.MustCompile(\"^[A-Z]{2}$\"))),\n\t\t\t// State cannot be empty, and must be a string consisting of five digits\n\t\t\tvalidation.Key(\"Zip\", validation.Required, validation.Match(regexp.MustCompile(\"^[0-9]{5}$\"))),\n\t\t)),\n\t),\n)\nfmt.Println(err)\n// Output:\n// Address: (State: must be in a valid format; Street: the length must be between 5 and 50.); Email: must be a valid email address.\n```\n\nWhen the map validation is performed, the keys are validated in the order they are specified in `Map`. \nAnd when each key is validated, its rules are also evaluated in the order they are associated with the key.\nIf a rule fails, an error is recorded for that key, and the validation will continue with the next key.\n\n\n### Validation Errors\n\nThe `validation.ValidateStruct` method returns validation errors found in struct fields in terms of `validation.Errors` \nwhich is a map of fields and their corresponding errors. Nil is returned if validation passes.\n\nBy default, `validation.Errors` uses the struct tags named `json` to determine what names should be used to \nrepresent the invalid fields. The type also implements the `json.Marshaler` interface so that it can be marshaled \ninto a proper JSON object. For example,\n\n```go\ntype Address struct {\n\tStreet string `json:\"street\"`\n\tCity   string `json:\"city\"`\n\tState  string `json:\"state\"`\n\tZip    string `json:\"zip\"`\n}\n\n// ...perform validation here...\n\nerr := a.Validate()\nb, _ := json.Marshal(err)\nfmt.Println(string(b))\n// Output:\n// {\"street\":\"the length must be between 5 and 50\",\"state\":\"must be in a valid format\"}\n```\n\nYou may modify `validation.ErrorTag` to use a different struct tag name.\n\nIf you do not like the magic that `ValidateStruct` determines error keys based on struct field names or corresponding\ntag values, you may use the following alternative approach:\n\n```go\nc := Customer{\n\tName:  \"Qiang Xue\",\n\tEmail: \"q\",\n\tAddress: Address{\n\t\tState:  \"Virginia\",\n\t},\n}\n\nerr := validation.Errors{\n\t\"name\": validation.Validate(c.Name, validation.Required, validation.Length(5, 20)),\n\t\"email\": validation.Validate(c.Name, validation.Required, is.Email),\n\t\"zip\": validation.Validate(c.Address.Zip, validation.Required, validation.Match(regexp.MustCompile(\"^[0-9]{5}$\"))),\n}.Filter()\nfmt.Println(err)\n// Output:\n// email: must be a valid email address; zip: cannot be blank.\n```\n\nIn the above example, we build a `validation.Errors` by a list of names and the corresponding validation results. \nAt the end we call `Errors.Filter()` to remove from `Errors` all nils which correspond to those successful validation \nresults. The method will return nil if `Errors` is empty.\n\nThe above approach is very flexible as it allows you to freely build up your validation error structure. You can use\nit to validate both struct and non-struct values. Compared to using `ValidateStruct` to validate a struct, \nit has the drawback that you have to redundantly specify the error keys while `ValidateStruct` can automatically \nfind them out.\n\n\n### Internal Errors\n\nInternal errors are different from validation errors in that internal errors are caused by malfunctioning code (e.g.\na validator making a remote call to validate some data when the remote service is down) rather\nthan the data being validated. When an internal error happens during data validation, you may allow the user to resubmit\nthe same data to perform validation again, hoping the program resumes functioning. On the other hand, if data validation\nfails due to data error, the user should generally not resubmit the same data again.\n\nTo differentiate internal errors from validation errors, when an internal error occurs in a validator, wrap it\ninto `validation.InternalError` by calling `validation.NewInternalError()`. The user of the validator can then check\nif a returned error is an internal error or not. For example,\n\n```go\nif err := a.Validate(); err != nil {\n\tif e, ok := err.(validation.InternalError); ok {\n\t\t// an internal error happened\n\t\tfmt.Println(e.InternalError())\n\t}\n}\n```\n\n\n## Validatable Types\n\nA type is validatable if it implements the `validation.Validatable` interface. \n\nWhen `validation.Validate` is used to validate a validatable value, if it does not find any error with the \ngiven validation rules, it will further call the value's `Validate()` method. \n\nSimilarly, when `validation.ValidateStruct` is validating a struct field whose type is validatable, it will call \nthe field's `Validate` method after it passes the listed rules.\n\n\u003e Note: When implementing `validation.Validatable`, do not call `validation.Validate()` to validate the value in its\n\u003e original type because this will cause infinite loops. For example, if you define a new type `MyString` as `string`\n\u003e and implement `validation.Validatable` for `MyString`, within the `Validate()` function you should cast the value \n\u003e to `string` first before calling `validation.Validate()` to validate it.\n\nIn the following example, the `Address` field of `Customer` is validatable because `Address` implements \n`validation.Validatable`. Therefore, when validating a `Customer` struct with `validation.ValidateStruct`,\nvalidation will \"dive\" into the `Address` field.\n\n```go\ntype Customer struct {\n\tName    string\n\tGender  string\n\tEmail   string\n\tAddress Address\n}\n\nfunc (c Customer) Validate() error {\n\treturn validation.ValidateStruct(\u0026c,\n\t\t// Name cannot be empty, and the length must be between 5 and 20.\n\t\tvalidation.Field(\u0026c.Name, validation.Required, validation.Length(5, 20)),\n\t\t// Gender is optional, and should be either \"Female\" or \"Male\".\n\t\tvalidation.Field(\u0026c.Gender, validation.In(\"Female\", \"Male\")),\n\t\t// Email cannot be empty and should be in a valid email format.\n\t\tvalidation.Field(\u0026c.Email, validation.Required, is.Email),\n\t\t// Validate Address using its own validation rules\n\t\tvalidation.Field(\u0026c.Address),\n\t)\n}\n\nc := Customer{\n\tName:  \"Qiang Xue\",\n\tEmail: \"q\",\n\tAddress: Address{\n\t\tStreet: \"123 Main Street\",\n\t\tCity:   \"Unknown\",\n\t\tState:  \"Virginia\",\n\t\tZip:    \"12345\",\n\t},\n}\n\nerr := c.Validate()\nfmt.Println(err)\n// Output:\n// Address: (State: must be in a valid format.); Email: must be a valid email address.\n```\n\nSometimes, you may want to skip the invocation of a type's `Validate` method. To do so, simply associate\na `validation.Skip` rule with the value being validated.\n\n### Maps/Slices/Arrays of Validatables\n\nWhen validating an iterable (map, slice, or array), whose element type implements the `validation.Validatable` interface,\nthe `validation.Validate` method will call the `Validate` method of every non-nil element.\nThe validation errors of the elements will be returned as `validation.Errors` which maps the keys of the\ninvalid elements to their corresponding validation errors. For example,\n\n```go\naddresses := []Address{\n\tAddress{State: \"MD\", Zip: \"12345\"},\n\tAddress{Street: \"123 Main St\", City: \"Vienna\", State: \"VA\", Zip: \"12345\"},\n\tAddress{City: \"Unknown\", State: \"NC\", Zip: \"123\"},\n}\nerr := validation.Validate(addresses)\nfmt.Println(err)\n// Output:\n// 0: (City: cannot be blank; Street: cannot be blank.); 2: (Street: cannot be blank; Zip: must be in a valid format.).\n```\n\nWhen using `validation.ValidateStruct` to validate a struct, the above validation procedure also applies to those struct \nfields which are map/slices/arrays of validatables. \n\n#### Each\n\nThe `Each` validation rule allows you to apply a set of rules to each element of an array, slice, or map.\n\n```go\ntype Customer struct {\n    Name      string\n    Emails    []string\n}\n\nfunc (c Customer) Validate() error {\n    return validation.ValidateStruct(\u0026c,\n        // Name cannot be empty, and the length must be between 5 and 20.\n\t\tvalidation.Field(\u0026c.Name, validation.Required, validation.Length(5, 20)),\n\t\t// Emails are optional, but if given must be valid.\n\t\tvalidation.Field(\u0026c.Emails, validation.Each(is.Email)),\n    )\n}\n\nc := Customer{\n    Name:   \"Qiang Xue\",\n    Emails: []Email{\n        \"valid@example.com\",\n        \"invalid\",\n    },\n}\n\nerr := c.Validate()\nfmt.Println(err)\n// Output:\n// Emails: (1: must be a valid email address.).\n```\n\n### Pointers\n\nWhen a value being validated is a pointer, most validation rules will validate the actual value pointed to by the pointer.\nIf the pointer is nil, these rules will skip the validation.\n\nAn exception is the `validation.Required` and `validation.NotNil` rules. When a pointer is nil, they\nwill report a validation error.\n\n\n### Types Implementing `sql.Valuer`\n\nIf a data type implements the `sql.Valuer` interface (e.g. `sql.NullString`), the built-in validation rules will handle\nit properly. In particular, when a rule is validating such data, it will call the `Value()` method and validate\nthe returned value instead.\n\n\n### Required vs. Not Nil\n\nWhen validating input values, there are two different scenarios about checking if input values are provided or not.\n\nIn the first scenario, an input value is considered missing if it is not entered or it is entered as a zero value\n(e.g. an empty string, a zero integer). You can use the `validation.Required` rule in this case.\n\nIn the second scenario, an input value is considered missing only if it is not entered. A pointer field is usually\nused in this case so that you can detect if a value is entered or not by checking if the pointer is nil or not.\nYou can use the `validation.NotNil` rule to ensure a value is entered (even if it is a zero value).\n\n\n### Embedded Structs\n\nThe `validation.ValidateStruct` method will properly validate a struct that contains embedded structs. In particular,\nthe fields of an embedded struct are treated as if they belong directly to the containing struct. For example,\n\n```go\ntype Employee struct {\n\tName string\n}\n\ntype Manager struct {\n\tEmployee\n\tLevel int\n}\n\nm := Manager{}\nerr := validation.ValidateStruct(\u0026m,\n\tvalidation.Field(\u0026m.Name, validation.Required),\n\tvalidation.Field(\u0026m.Level, validation.Required),\n)\nfmt.Println(err)\n// Output:\n// Level: cannot be blank; Name: cannot be blank.\n```\n\nIn the above code, we use `\u0026m.Name` to specify the validation of the `Name` field of the embedded struct `Employee`.\nAnd the validation error uses `Name` as the key for the error associated with the `Name` field as if `Name` a field\ndirectly belonging to `Manager`.\n\nIf `Employee` implements the `validation.Validatable` interface, we can also use the following code to validate\n`Manager`, which generates the same validation result:\n\n```go\nfunc (e Employee) Validate() error {\n\treturn validation.ValidateStruct(\u0026e,\n\t\tvalidation.Field(\u0026e.Name, validation.Required),\n\t)\n}\n\nerr := validation.ValidateStruct(\u0026m,\n\tvalidation.Field(\u0026m.Employee),\n\tvalidation.Field(\u0026m.Level, validation.Required),\n)\nfmt.Println(err)\n// Output:\n// Level: cannot be blank; Name: cannot be blank.\n```\n\n\n### Conditional Validation\n\nSometimes, we may want to validate a value only when certain condition is met. For example, we want to ensure the \n`unit` struct field is not empty only when the `quantity` field is not empty; or we may want to ensure either `email`\nor `phone` is provided. The so-called conditional validation can be achieved with the help of `validation.When`.\nThe following code implements the aforementioned examples:\n\n```go\nresult := validation.ValidateStruct(\u0026a,\n    validation.Field(\u0026a.Unit, validation.When(a.Quantity != \"\", validation.Required).Else(validation.Nil)),\n    validation.Field(\u0026a.Phone, validation.When(a.Email == \"\", validation.Required.Error('Either phone or Email is required.')),\n    validation.Field(\u0026a.Email, validation.When(a.Phone == \"\", validation.Required.Error('Either phone or Email is required.')),\n)\n```\n\nNote that `validation.When` and `validation.When.Else` can take a list of validation rules. These rules will be executed only when the condition is true (When) or false (Else).\n\nThe above code can also be simplified using the shortcut `validation.Required.When`:\n\n```go\nresult := validation.ValidateStruct(\u0026a,\n    validation.Field(\u0026a.Unit, validation.Required.When(a.Quantity != \"\"), validation.Nil.When(a.Quantity == \"\")),\n    validation.Field(\u0026a.Phone, validation.Required.When(a.Email == \"\").Error('Either phone or Email is required.')),\n    validation.Field(\u0026a.Email, validation.Required.When(a.Phone == \"\").Error('Either phone or Email is required.')),\n)\n```\n\n### Customizing Error Messages\n\nAll built-in validation rules allow you to customize their error messages. To do so, simply call the `Error()` method\nof the rules. For example,\n\n```go\ndata := \"2123\"\nerr := validation.Validate(data,\n\tvalidation.Required.Error(\"is required\"),\n\tvalidation.Match(regexp.MustCompile(\"^[0-9]{5}$\")).Error(\"must be a string with five digits\"),\n)\nfmt.Println(err)\n// Output:\n// must be a string with five digits\n```\n\nYou can also customize the pre-defined error(s) of a built-in rule such that the customization applies to *every*\ninstance of the rule. For example, the `Required` rule uses the pre-defined error `ErrRequired`. You can customize it\nduring the application initialization:\n```go\nvalidation.ErrRequired = validation.ErrRequired.SetMessage(\"the value is required\") \n```\n\n### Error Code and Message Translation\n\nThe errors returned by the validation rules implement the `Error` interface which contains the `Code()` method \nto provide the error code information. While the message of a validation error is often customized, the code is immutable.\nYou can use error code to programmatically check a validation error or look for the translation of the corresponding message.\n\nIf you are developing your own validation rules, you can use `validation.NewError()` to create a validation error which\nimplements the aforementioned `Error` interface.\n\n## Creating Custom Rules\n\nCreating a custom rule is as simple as implementing the `validation.Rule` interface. The interface contains a single\nmethod as shown below, which should validate the value and return the validation error, if any:\n\n```go\n// Validate validates a value and returns an error if validation fails.\nValidate(value interface{}) error\n```\n\nIf you already have a function with the same signature as shown above, you can call `validation.By()` to turn\nit into a validation rule. For example,\n\n```go\nfunc checkAbc(value interface{}) error {\n\ts, _ := value.(string)\n\tif s != \"abc\" {\n\t\treturn errors.New(\"must be abc\")\n\t}\n\treturn nil\n}\n\nerr := validation.Validate(\"xyz\", validation.By(checkAbc))\nfmt.Println(err)\n// Output: must be abc\n```\n\nIf your validation function takes additional parameters, you can use the following closure trick:\n\n```go\nfunc stringEquals(str string) validation.RuleFunc {\n\treturn func(value interface{}) error {\n\t\ts, _ := value.(string)\n        if s != str {\n            return errors.New(\"unexpected string\")\n        }\n        return nil\n    }\n}\n\nerr := validation.Validate(\"xyz\", validation.By(stringEquals(\"abc\")))\nfmt.Println(err)\n// Output: unexpected string\n```\n\n\n### Rule Groups\n\nWhen a combination of several rules are used in multiple places, you may use the following trick to create a \nrule group so that your code is more maintainable.\n\n```go\nvar NameRule = []validation.Rule{\n\tvalidation.Required,\n\tvalidation.Length(5, 20),\n}\n\ntype User struct {\n\tFirstName string\n\tLastName  string\n}\n\nfunc (u User) Validate() error {\n\treturn validation.ValidateStruct(\u0026u,\n\t\tvalidation.Field(\u0026u.FirstName, NameRule...),\n\t\tvalidation.Field(\u0026u.LastName, NameRule...),\n\t)\n}\n```\n\nIn the above example, we create a rule group `NameRule` which consists of two validation rules. We then use this rule\ngroup to validate both `FirstName` and `LastName`.\n\n\n## Context-aware Validation\n\nWhile most validation rules are self-contained, some rules may depend dynamically on a context. A rule may implement the\n`validation.RuleWithContext` interface to support the so-called context-aware validation.\n \nTo validate an arbitrary value with a context, call `validation.ValidateWithContext()`. The `context.Conext` parameter \nwill be passed along to those rules that implement `validation.RuleWithContext`.\n\nTo validate the fields of a struct with a context, call `validation.ValidateStructWithContext()`. \n\nYou can define a context-aware rule from scratch by implementing both `validation.Rule` and `validation.RuleWithContext`. \nYou can also use `validation.WithContext()` to turn a function into a context-aware rule. For example,\n\n\n```go\nrule := validation.WithContext(func(ctx context.Context, value interface{}) error {\n\tif ctx.Value(\"secret\") == value.(string) {\n\t    return nil\n\t}\n\treturn errors.New(\"value incorrect\")\n})\nvalue := \"xyz\"\nctx := context.WithValue(context.Background(), \"secret\", \"example\")\nerr := validation.ValidateWithContext(ctx, value, rule)\nfmt.Println(err)\n// Output: value incorrect\n```\n\nWhen performing context-aware validation, if a rule does not implement `validation.RuleWithContext`, its\n`validation.Rule` will be used instead.\n\n\n## Built-in Validation Rules\n\nThe following rules are provided in the `validation` package:\n\n* `In(...interface{})`: checks if a value can be found in the given list of values.\n* `NotIn(...interface{})`: checks if a value is NOT among the given list of values.\n* `Length(min, max int)`: checks if the length of a value is within the specified range.\n  This rule should only be used for validating strings, slices, maps, and arrays.\n* `RuneLength(min, max int)`: checks if the length of a string is within the specified range.\n  This rule is similar as `Length` except that when the value being validated is a string, it checks\n  its rune length instead of byte length.\n* `Min(min interface{})` and `Max(max interface{})`: checks if a value is within the specified range.\n  These two rules should only be used for validating int, uint, float and time.Time types.\n* `Match(*regexp.Regexp)`: checks if a value matches the specified regular expression.\n  This rule should only be used for strings and byte slices.\n* `Date(layout string)`: checks if a string value is a date whose format is specified by the layout.\n  By calling `Min()` and/or `Max()`, you can check additionally if the date is within the specified range.\n* `Required`: checks if a value is not empty (neither nil nor zero).\n* `NotNil`: checks if a pointer value is not nil. Non-pointer values are considered valid.\n* `NilOrNotEmpty`: checks if a value is a nil pointer or a non-empty value. This differs from `Required` in that it treats a nil pointer as valid.\n* `Nil`: checks if a value is a nil pointer.\n* `Empty`: checks if a value is empty. nil pointers are considered valid.\n* `Skip`: this is a special rule used to indicate that all rules following it should be skipped (including the nested ones).\n* `MultipleOf`: checks if the value is a multiple of the specified range.\n* `Each(rules ...Rule)`: checks the elements within an iterable (map/slice/array) with other rules.\n* `When(condition, rules ...Rule)`: validates with the specified rules only when the condition is true.\n* `Else(rules ...Rule)`: must be used with `When(condition, rules ...Rule)`, validates with the specified rules only when the condition is false.\n\nThe `is` sub-package provides a list of commonly used string validation rules that can be used to check if the format\nof a value satisfies certain requirements. Note that these rules only handle strings and byte slices and if a string\n or byte slice is empty, it is considered valid. You may use a `Required` rule to ensure a value is not empty.\nBelow is the whole list of the rules provided by the `is` package:\n\n* `Email`: validates if a string is an email or not. It also checks if the MX record exists for the email domain.\n* `EmailFormat`: validates if a string is an email or not. It does NOT check the existence of the MX record.\n* `URL`: validates if a string is a valid URL\n* `RequestURL`: validates if a string is a valid request URL\n* `RequestURI`: validates if a string is a valid request URI\n* `Alpha`: validates if a string contains English letters only (a-zA-Z)\n* `Digit`: validates if a string contains digits only (0-9)\n* `Alphanumeric`: validates if a string contains English letters and digits only (a-zA-Z0-9)\n* `UTFLetter`: validates if a string contains unicode letters only\n* `UTFDigit`: validates if a string contains unicode decimal digits only\n* `UTFLetterNumeric`: validates if a string contains unicode letters and numbers only\n* `UTFNumeric`: validates if a string contains unicode number characters (category N) only\n* `LowerCase`: validates if a string contains lower case unicode letters only\n* `UpperCase`: validates if a string contains upper case unicode letters only\n* `Hexadecimal`: validates if a string is a valid hexadecimal number\n* `HexColor`: validates if a string is a valid hexadecimal color code\n* `RGBColor`: validates if a string is a valid RGB color in the form of rgb(R, G, B)\n* `Int`: validates if a string is a valid integer number\n* `Float`: validates if a string is a floating point number\n* `UUIDv3`: validates if a string is a valid version 3 UUID\n* `UUIDv4`: validates if a string is a valid version 4 UUID\n* `UUIDv5`: validates if a string is a valid version 5 UUID\n* `UUID`: validates if a string is a valid UUID\n* `CreditCard`: validates if a string is a valid credit card number\n* `ISBN10`: validates if a string is an ISBN version 10\n* `ISBN13`: validates if a string is an ISBN version 13\n* `ISBN`: validates if a string is an ISBN (either version 10 or 13)\n* `JSON`: validates if a string is in valid JSON format\n* `ASCII`: validates if a string contains ASCII characters only\n* `PrintableASCII`: validates if a string contains printable ASCII characters only\n* `Multibyte`: validates if a string contains multibyte characters\n* `FullWidth`: validates if a string contains full-width characters\n* `HalfWidth`: validates if a string contains half-width characters\n* `VariableWidth`: validates if a string contains both full-width and half-width characters\n* `Base64`: validates if a string is encoded in Base64\n* `DataURI`: validates if a string is a valid base64-encoded data URI\n* `E164`: validates if a string is a valid E164 phone number (+19251232233)\n* `CountryCode2`: validates if a string is a valid ISO3166 Alpha 2 country code\n* `CountryCode3`: validates if a string is a valid ISO3166 Alpha 3 country code\n* `DialString`: validates if a string is a valid dial string that can be passed to Dial()\n* `MAC`: validates if a string is a MAC address\n* `IP`: validates if a string is a valid IP address (either version 4 or 6)\n* `IPv4`: validates if a string is a valid version 4 IP address\n* `IPv6`: validates if a string is a valid version 6 IP address\n* `Subdomain`: validates if a string is valid subdomain\n* `Domain`: validates if a string is valid domain\n* `DNSName`: validates if a string is valid DNS name\n* `Host`: validates if a string is a valid IP (both v4 and v6) or a valid DNS name\n* `Port`: validates if a string is a valid port number\n* `MongoID`: validates if a string is a valid Mongo ID\n* `Latitude`: validates if a string is a valid latitude\n* `Longitude`: validates if a string is a valid longitude\n* `SSN`: validates if a string is a social security number (SSN)\n* `Semver`: validates if a string is a valid semantic version\n\n## Credits\n\nThe `is` sub-package wraps the excellent validators provided by the [govalidator](https://github.com/asaskevich/govalidator) package.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGo-ozzo%2Fozzo-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGo-ozzo%2Fozzo-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGo-ozzo%2Fozzo-validation/lists"}