{"id":41756206,"url":"https://github.com/liangyaopei/checker","last_synced_at":"2026-01-25T01:37:02.671Z","repository":{"id":48372095,"uuid":"312740554","full_name":"liangyaopei/checker","owner":"liangyaopei","description":"Golang parameter validation, which can replace go-playground/validator, includes ncluding Cross Field, Map, Slice and Array diving, provides readable,flexible, configurable validation.","archived":false,"fork":false,"pushed_at":"2021-07-29T13:44:09.000Z","size":224,"stargazers_count":85,"open_issues_count":2,"forks_count":12,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-19T19:46:05.832Z","etag":null,"topics":["govalidator","validate","validation","validator","verification"],"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/liangyaopei.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}},"created_at":"2020-11-14T03:52:30.000Z","updated_at":"2024-05-08T11:34:39.000Z","dependencies_parsed_at":"2022-08-28T11:41:30.028Z","dependency_job_id":null,"html_url":"https://github.com/liangyaopei/checker","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/liangyaopei/checker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liangyaopei%2Fchecker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liangyaopei%2Fchecker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liangyaopei%2Fchecker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liangyaopei%2Fchecker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liangyaopei","download_url":"https://codeload.github.com/liangyaopei/checker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liangyaopei%2Fchecker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28740978,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T01:25:41.653Z","status":"ssl_error","status_checked_at":"2026-01-25T01:25:34.364Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["govalidator","validate","validation","validator","verification"],"created_at":"2026-01-25T01:37:02.590Z","updated_at":"2026-01-25T01:37:02.655Z","avatar_url":"https://github.com/liangyaopei.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Checker\n[![Go Report Card](https://goreportcard.com/badge/github.com/liangyaopei/checker)](https://goreportcard.com/report/github.com/liangyaopei/checker)\n[![GoDoc](https://godoc.org/github.com/liangyaopei/checker?status.svg)](http://godoc.org/github.com/liangyaopei/checker)\n[![Go Reference](https://pkg.go.dev/badge/github.com/liangyaopei/checker.svg)](https://pkg.go.dev/github.com/liangyaopei/checker)\n[![Build Status](https://travis-ci.com/liangyaopei/checker.svg?branch=master)](https://travis-ci.com/liangyaopei/checker)\n![License](https://img.shields.io/dub/l/vibe-d.svg)\n[![Coverage Status](https://coveralls.io/repos/github/liangyaopei/checker/badge.svg?branch=master)](https://coveralls.io/github/liangyaopei/checker?branch=master)\n\n[中文版本](README_zh.md)\n\n`Checker` is a parameter validation package, can be use in struct/non-struct validation, including cross field validation in struct, elements validation in Slice/Array/Map, and provides customized validation rule.\n\n## Requirements\n\nGo 1.13 or above.\n\n## Installation\n\n```\ngo get -u github.com/liangyaopei/checker\n```\n\n\n\n## Usage\n\nWhen use `Add` to add rule，`fieldExpr` has three situations：\n- `fieldExpr` is empty，validate the value directly.\n- `fieldExpr` is single field，fetch value in struct, then validate.\n- `fieldExpr` is string separated by `.`, fetch value in struct according hierarchy of struct, then validate.\n\nWhen fetching value by `fieldExpr`, if the field is pointer, it will fetch the underlying value of pointer\nto validate; if the field is nil pointer, it failed validation rule. \n\nFor special use of validating nil pointer, `Nil` rule can be used.\n\nexample from `checker_test.go`\n```go\n// Item.Email is the format of email address\ntype Item struct {\n\tInfo  typeInfo\n\tEmail string\n}\n\ntype typeStr string\n// Item.Info.Type = \"range\",typeInfo.Type 's length is 2，elements with format of \"2006-01-02\"\n// Item.Info.Type = \"last\",typeInfo.Type 'is length is 1，elements is positive integer，Granularity is one of day/week/month\ntype typeInfo struct {\n\tType        typeStr\n\tRange       []string\n\tUnit        string\n\tGranularity string\n}\n\n\n// rules are as follow\nrule := And(\n\t\tEmail(\"Email\"),\n\t\tField(\"Info\",\n\t\t\tOr(\n\t\t\t\tAnd(\n\t\t\t\t\tEqStr(\"Type\", \"range\"),\n\t\t\t\t\tLength(\"Range\", 2, 2),\n\t\t\t\t\tArray(\"Range\", isDatetime(\"\", \"2006-01-02\")),\n\t\t\t\t),\n\t\t\t\tAnd(\n\t\t\t\t\tEqStr(\"Type\", \"last\"),\n\t\t\t\t\tInStr(\"Granularity\", \"day\", \"week\", \"month\"),\n\t\t\t\t\tNumber(\"Unit\"),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t)\nitemChecker := NewChecker()\n// validate parameter\nitemChecker.Add(rule, \"wrong item\")\n```\n`rule` variable in above code constructs a rule tree.\n![rule tree](rule_tree.png)\n\nTo Note that, different rule tree can produce same validation rule, above `rule` can be rewritten as\n```go\nrule := And(\n\t\tEmail(\"Email\"),\n\t\tOr(\n\t\t\tAnd(\n\t\t\t\tEqStr(\"Info.Type\", \"range\"),\n\t\t\t\tLength(\"Info.Range\", 2, 2),\n\t\t\t\tArray(\"Info.Range\", Time(\"\", \"2006-01-02\")),\n\t\t\t),\n\t\t\tAnd(\n\t\t\t\tEqStr(\"Info.Type\", \"last\"),\n\t\t\t\tInStr(\"Info.Granularity\", \"day\", \"week\", \"month\"),\n\t\t\t\tNumber(\"Info.Unit\"),\n\t\t\t),\n\t\t),\n\t)\n```\n![rule tree2](rule_tree2.png)\n\nAlthough rule trees are different, `fieldExpr` of leaf nodes in trees are same, which can be used as cache,\nand the validation logic is same.\n\n\n## Rule\n`Rule` is an interface, it has many implementations. Its implementations can be categorized into\ntwo kinds: composite rule and singleton rule.\n\n### Composite Rule\n\nComposite Rule contains other rules.\n\n| Name                                                       | Usage                                                 |\n| ---------------------------------------------------------- | ----------------------------------------------------- |\n| `Field(fieldExpr string, rule Rule) Rule`                  | Applies `rule` to validate `fieldExpr`                |\n| `And(rules ...Rule) Rule`                                  | It needs all rules pass                               |\n| `Or(rules ...Rule) Rule`                                   | It needs any rule passed                              |\n| `Not(innerRule Rule) Rule`                                 | opposite the rule                                     |\n| `Array(fieldExpr string, innerRule Rule) Rule`             | Applies rule to elements in array                     |\n| `Map(fieldExpr string, keyRule Rule, valueRule Rule) Rule` | Applies keyRule and valueRule to key and value in map |\n\n\n\n### Singleton Rule\n\nSingleton Rule can  be categorized into comparison rule, enum rule and format rule.\n\n#### Comparison Rule\n\n\nComparison Rule can be categorized into single field comparison rule and multi-field comparison rule\n\n\n\nsingle field comparison rule includes:\n\n| Name                                              |\n| ------------------------------------------------- |\n| `EqInt(filedExpr string, equivalent int) Rule`    |\n| `NeInt(filedExpr string, inequivalent int) Rule`  |\n| `RangeInt(filedExpr string, ge int, le int) Rule` |\n\n\nIt also has the implementation of `uint`, `string`，`float`，`time.Time` , `Comparable`.\n\n\n\nmulti-field comparison rule includes \n\n| Name                                                         |\n| ------------------------------------------------------------ |\n| `CrossComparable(fieldExprLeft string, fieldExprRight string, op operand) Rule` |\n\n\n`fieldExprLeft`，`fieldExprRight` is to located the field involving comparsion, `op` is the operand.\n\n`CrossComparable` supports `int`\\`uint`\\`float`\\`string`\\`time.Time`\\`Comparable`.\n\n####  Enum Rule\n\nEnum Rule includes\n\n| Name                                              |\n| ------------------------------------------------- |\n| `InStr(filedExpr string, enum ...string) Rule`    |\n| `InInt(filedExpr string, enum ...int) Rule`       |\n| `InUint(filedExpr string, enum ...uint) Rule`     |\n| `InFloat(filedExpr string, enum ...float64) Rule` |\n\n\n\n#### Format Rule\n\nFormat Rule includes\n\n| Name                            |\n| ------------------------------- |\n| `Email(fieldExpr string) Rule`  |\n| `Number(fieldExpr string) Rule` |\n| `URL(fieldExpr string) Rule`    |\n| `Ip(fieldExpr string) Rule`     |\n\netc.\n\n\n\n#### Customized Rule\n\nIn addition to above rules, user can pass validation function to `Custome` to achieve purpose of \nimplementing customized rule, refer to [example](_example/custom/main.go)\n\n\n\n\n\n## Checker\n\n\n`Checekr` is an interface\n\n- `Add(rule Rule, prompt string)`. Add rule and error prompt of failing the rule.\n- `Check(param interface{}) (bool, string, string)`. Validate a parameter. It returns if it passes the rule, error prompt and error message to tell which field doesn't pass which rule.\n\n## Error log And Customized Error Prompt\n\nWhen defining rules, it can define the error prompt when rule failed.[example](_example/prompt/main.go)\n```go\nrule := checker.And(\n\t\tchecker.Email(\"Email\").Prompt(\"Wrong email format\") // [1],\n\t\tchecker.And(\n\t\t\tchecker.EqStr(\"Info.Type\", \"range\"),\n\t\t\tchecker.Length(\"Info.Range\", 2, 2).Prompt(\"Range's length should be 2\") // [2],\n\t\t\tchecker.Array(\"Info.Range\", checker.Time(\"\", \"2006-01-02\")).\n\t\t\t\tPrompt(\"Range's element should be time format\") // [3],\n\t\t),\n\t)\n\n\tvalidator := checker.NewChecker()\n\tvalidator.Add(rule, \"wrong parameter\") // [4]\n    isValid, prompt, errMsg := validator.Check(item)\n```\n\nWhen rule fails, checker tries to return the rule's prompt([1]/[2]/[3] in code). If rule doesn't\nhave its prompt, checker returns the prompt when adding the rule([4] in code).\n\n\n`errMsg` is error log, is used to locate the filed that fails, refer it to [example](_example/composite/main.go)\n\n\n## Field Cache\nFrom above graphic representation of rule tree, it can be found that when leaf node\nwith same field expression, its value can be cached to reduce the cost of reflection.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliangyaopei%2Fchecker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliangyaopei%2Fchecker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliangyaopei%2Fchecker/lists"}