{"id":21214293,"url":"https://github.com/goindow/validator","last_synced_at":"2025-03-15T00:19:43.715Z","repository":{"id":143903782,"uuid":"183343379","full_name":"goindow/validator","owner":"goindow","description":"Package validator 实现了一个支持场景/国际化/自定义错误/自定义验证规则的 map[string]interface{} 元素批量验证器","archived":false,"fork":false,"pushed_at":"2019-10-15T06:50:12.000Z","size":165,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-21T16:23:15.471Z","etag":null,"topics":["go-validator","validator"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/goindow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2019-04-25T02:43:41.000Z","updated_at":"2021-12-27T09:37:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"8f9b2d23-625e-4423-a7a5-20d408187b6a","html_url":"https://github.com/goindow/validator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goindow%2Fvalidator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goindow%2Fvalidator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goindow%2Fvalidator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goindow%2Fvalidator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/goindow","download_url":"https://codeload.github.com/goindow/validator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243663598,"owners_count":20327310,"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-validator","validator"],"created_at":"2024-11-20T21:27:09.054Z","updated_at":"2025-03-15T00:19:43.695Z","avatar_url":"https://github.com/goindow.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# validator\nPackage validator 实现了一个支持场景/国际化/自定义错误/自定义验证规则的 map[string]interface{} 元素批量验证器，意在支持各种框架的 model 层实现自动验证，亦可单独使用\n\n## 索引\n- [说明](#说明)\n- [特性](#特性)\n- [安装](#安装)\n- [示例](#示例)\n- [如何定义验证规则](#如何定义验证规则)\n- [国际化](#国际化)\n- [自定义错误信息](#自定义错误信息)\n- [自定义验证器](#自定义验证器)\n- [内置验证器](#内置验证器)\n- [自动验证](#自动验证)\n\n## 说明\n- 该验证器是 ***逻辑验证器***（float64(10)/int32(10)/\"10\" 均可被 intValidator 验证通过）而不是 ***强类型验证器***\n- 考虑到经过 encoding/json 解析后的数字类型均被解析为 float64，强类型验证器不太可用，故此设计\n- 如果需要强类型验证，可以使用 funcValidator 自定义验证函数，或使用 AddValidator 自定义验证器\n\n## 特性\n- 支持场景\n- 支持国际化\n- 支持批量验证\n- 支持自定义验证器\n- 支持自定义错误信息\n\n## 安装\n```bash\ngo get github.com/goindow/validator\n```\n\n## 示例\n- [配合框架的 model 层实现自动验证](#自动验证)\n- 独立使用\n```go\npackage main\n\nimport (\n    \"github.com/goindow/validator\"\n    \"fmt\"\n)\n\nfunc main() {\n    user := map[string]interface{}{\n        // \"username\": \"hyb\",\n        \"password\": \"******\",\n        \"gender\": \"male\",\n        \"age\": 17,\n        \"weight\": \"53kg\",\n        \"email\": \"hyb76788424#163.com\",\n    }\n\n    rules := validator.Rules{\n        \"create\": {\n            { Attr: []string{\"username\", \"password\"}, Rule: \"required\" },\n            { Attr: \"password\", Rule: \"regex\", Pattern: `[A-Z]{1}\\w{5,}`, Message: \"密码必须由大写字母开头\"},\n            { Attr: \"gender\", Rule: \"in\", Enum: []string{\"0\", \"1\"} },\n            { Attr: \"age\", Rule: \"int\", Min: 18 },\n            { Attr: \"weight\", Rule: \"number\", Symbol: 1 },\n            { Attr: \"email\", Rule: \"email\" },\n        },\n        \"read\": {\n            { Attr: \"id\", Rule: \"int\", Symbol: 1 },\n        },\n    }\n\n    if e := validator.New().Validate(rules, user, \"create\"); e != nil {\n        // todo: handle errors\n        for _, i := range e {\n            for k, v := range i {\n                fmt.Printf(\"%v =\u003e %v\\n\", k, v)\n            }\n        }\n        // username =\u003e 不能为空\n        // password =\u003e 密码必须由大写字母开头\n        // gender =\u003e 只能是 [0、1] 中的一个\n        // age =\u003e 必须是不小于 18 的整数\n        // weight =\u003e 必须是数字\n        // email =\u003e 无效的 email\n    }\n    // todo: do something\n}\n```\n\n## 如何定义验证规则\n- ***validator.Rule*** struct 验证规则\n    - ***Attr***        interface{}    **必选**，待验证属性，单个属性 string，多个属性 []string，其他类型或未定义将 panic\n    - ***Rule***        string         **必选**，验证规则，即验证器，不存在的验证器或未定义将 panic\n    - ***Message***     string         **可选**，自定义错误信息\n    - ***Required***    bool           **可选**，可空限制，作用于除 requiredValidator 外的所有验证器，false(默认) - 有值验证/无值跳过，true - 有值验证/无值报错\n    - ***Symbol***      int64          **可选**，符号限制，作用于 numberValidator、integerValidator、decimalValidator，0(默认) - 正/负数，\u003e0 - 正数(不包含0)，\u003c0 - 负数(不包含0)\n    - ***Max***         interface{}    **可选**，最大限制，作用于 stringValidator、numberValidator、integerValidator、decimalValidator\n    - ***Min***         interface{}    **可选**，最小限制，同 Max\n    - ***Enum***        []string       **必选（inValidator）**，枚举限制，作用于 inValidator\n    - ***Func***        validator.F    **必选（funcValidator）**，自定义验证函数，作用于 funcValidator\n    - ***Pattern***     string         **必选（regexValidator）**，正则匹配模式，作用于 regexValidator\n- ***validator.Scence*** string 场景\n- ***validator.ScenceRules*** []validator.Rule 验证规则集 - 单一场景\n- ***validator.Rules map[Scence]ScenceRules*** 验证规则集 - 所有场景\n```go\nrules := validator.Rules{ // validator.Rules\n    // validator.ScenceRules\n    \"create\": { // validator.Scence\n        { Attr: []string{\"username\", \"password\"}, Rule: \"required\" }, // validator.Rule\n        { Attr: \"password\", Rule: \"regex\", Pattern: `[A-Z]{1}\\w{5,}`, Message: \"密码必须由大写字母开头\"},\n        { Attr: \"gender\", Rule: \"in\", Enum: []string{\"0\", \"1\"} },\n        { Attr: \"age\", Rule: \"int\", Min: 18 },\n        { Attr: \"weight\", Rule: \"number\", Symbol: 1 },\n        { Attr: \"email\", Rule: \"email\" },\n    },\n    \"read\": {\n        { Attr: \"id\", Rule: \"int\", Symbol: 1 },\n    },\n}\n```\n\n## 国际化\n- Lang(lang string) *validator\n- 在 i18n 下，新建错误信息对应的语言文件，格式参考已有文件，包本身自带两种语言(zh_cn、en_us)，默认语言为 zh_cn\n```go\n// touch ./i18n/en_us.go\nv := validator.New().Lang(\"en_us\")\n```\n\n## 自定义错误信息\n- Rule.Message string\n```go\nrules := validator.Rules{\n    \"create\": {\n        { Attr: \"password\", Rule: \"regex\", Pattern: `[A-Z]{1}\\w{5,}`, Message: \"密码必须由大写字母开头\"},\n    }\n}\n```\n\n## 自定义验证器\n- AddValidator(name string, customValidator F)\n```go\npackage main\n\nimport (\n    \"github.com/goindow/validator\"\n    \"fmt\"\n)\n\nfunc main() {\n    v := validator.New()\n\n    // 自定义验证器，类型为 validator.F\n    var oneValidator validator.F = func(attr string, rule validator.Rule, obj validator.M) validator.E {\n        if _, ok := obj[attr]; !ok {\n            return validator.E{attr: \"not found\"}\n        }\n        if obj[attr] != 1 {\n            e := rule.Message\n            if e == \"\" {\n                e = \"必须等于一\"\n            }\n            return validator.E{attr: e} \n        }\n        return nil\n    }\n\n    // 挂载\n    v.AddValidator(\"one\", oneValidator)\n\n    // 使用\n    user := map[string]interface{}{\n        \"name\": \"hyb\",\n    }\n    rules := validator.Rules{\n        \"someone\": {\n            {Attr: \"name\", Rule: \"one\"},\n        },\n    }\n    e := v.Validate(rules, user, \"someone\")\n    fmt.Println(e)\n    // [map[name:必须等于一]]\n}\n```\n\n## 内置验证器\n- [funcValidator](#funcValidator)\n- [requiredValidator](#requiredValidator)\n- [inValidator](#inValidator)\n- [stringValidator](#stringValidator)\n- [integerValidator](#integerValidator)\n- [decimalValidator](#decimalValidator)\n- [numberValidator](#numberValidator)\n- [booleanValidator](#booleanValidator)\n- [ipValidator](#ipValidator)\n- [regexValidator](#regexValidator)\n- [emailValidator](#emailValidator)\n- [telValidator](#telValidator)\n- [mobileValidator](#mobileValidator)\n- [zipcodeValidator](#zipcodeValidator)\n\n### funcValidator\n- 使用 Rule.Func 定义的函数来验证本条规则，Rule.Func 的类型是 validator.F\n- Rule.Rule        string         必选    func\n- Rule.Required    bool           可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Func        validator.F    必选    使用 Rule.Func 来验证本条 Rule\n```go\nrule := {Attr: \"password\", Rule: \"func\", Func: func(attr string, rule validator.Rule, obj validator.M) validator.E {\n    if obj[\"password\"] != obj[\"rpassword\"] {\n        return validator.E{attr: \"两次输入不一致\"}\n    }\n    return nil\n}}\n```\n\n### requiredValidator\n- 必填\n- Rule.Rule        string      必选    required\n```go\nrule := {Attr: []string{\"username\", \"password\"}, Rule: \"required\"}\n```\n\n### inValidator\n- 枚举，被验证字段支持类型 int64、int32、int16、int8、int、float64、float32、string、bool\n- Rule.Rule        string      必选    in\n- Rule.Required    bool        可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Enum        []string    必选    被验证字段必须在 Rule.Enum 中\n```go\nrule := {Attr: \"gender\", Rule: \"in\", Enum: {\"male\", \"female\", \"unknown\"}} // 默认，所有规则，有值验证，无值跳过\nrule := {Attr: \"gender\", Rule: \"in\", Enum: {\"male\", \"female\", \"unknown\"}, Required: true} // 有值验证，无值报 required 错误\n```\n\n### stringValidator\n- 字符串\n- Rule.Rule        string    必选    string\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Max         int       可选    被验证字段长度不能大于 Rule.Max\n- Rule.Min         in        可选    被验证字段长度不能小于 Rule.Min\n```go\nrule := {Attr: \"name\", Rule: \"string\"}\nrule := {Attr: \"name\", Rule: \"string\", Min: 6} // utf8 字符数，即字符串长度，兼容中文\nrule := {Attr: \"name\", Rule: \"string\", Min: 6, Max: 18}\nrule := {Attr: \"name\", Rule: \"string\", Min: 6, Max: 18, Required: true}\n```\n\n### integerValidator\n- 整数，被验证字段支持类型 int64、int32、int16、int8、int、float64、float32、string\n- Rule.Rule        string    必选    integer/int\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Symbol      int64     可选    0(默认) - 正/负数，\u003e0 - 正数(不包含0)，\u003c0 - 负数(不包含0)\n- Rule.Max         int       可选    被验证字段大小不能大于 Rule.Max\n- Rule.Min         int       可选    被验证字段大小不能小于 Rule.Min\n```go\n// int 为 integer 的别名，都指向 integerValidator 验证器\nrule := {Attr: \"age\", Rule: \"int\"}\nrule := {Attr: \"age\", Rule: \"integer\", Symobl: 1} // 正整数\nrule := {Attr: \"age\", Rule: \"integer\", Min: 18}\nrule := {Attr: \"age\", Rule: \"integer\", Min: 18, Max: 18} // == 18\nrule := {Attr: \"age\", Rule: \"integer\", Min: 18, Max: 35, Required: true}\n\n// float64(18)、float32(18)、\"18\" 都会被认为是整数\n```\n\n### decimalValidator\n- 小数，被验证字段支持类型 float64、float32、string\n- Rule.Rule        string         必选    decimal/float\n- Rule.Required    bool           可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Symbol      int64          可选    0(默认) - 正/负数，\u003e0 - 正数(不包含0)，\u003c0 - 负数(不包含0)\n- Rule.Max         int|float64    可选    被验证字段大小不能大于 Rule.Max\n- Rule.Min         int|float64    可选    被验证字段大小不能小于 Rule.Min\n```go\n// float 为 decimal 的别名，都指向 decimalValidator 验证器\nrule := {Attr: \"field\", Rule: \"float\"}\nrule := {Attr: \"field\", Rule: \"decimal\", Symobl: -1} // 负小数\nrule := {Attr: \"field\", Rule: \"decimal\", Min: 2}\nrule := {Attr: \"field\", Rule: \"decimal\", Min: 3.14, Max: 3.14} // == 3.14\nrule := {Attr: \"field\", Rule: \"decimal\", Min: 3, Max: 3.14, Required: true}\n\n// float64(18)、float32(18)、\"18\" 没有小数位会验证失败\n```\n\n### numberValidator\n- 数字，被验证字段支持类型 int64、int32、int16、int8、int、float64、float32、string\n- Rule.Rule        string         必选    number\n- Rule.Required    bool           可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Symbol      int64          可选    0(默认) - 正/负数，\u003e0 - 正数(不包含0)，\u003c0 - 负数(不包含0)\n- Rule.Max         int|float64    可选    被验证字段大小不能大于 Rule.Max\n- Rule.Min         int|float64    可选    被验证字段大小不能小于 Rule.Min\n```go\nrule := {Attr: \"weight\", Rule: \"number\"}\nrule := {Attr: \"weight\", Rule: \"number\", Symobl: 1}\nrule := {Attr: \"weight\", Rule: \"number\", Min: 45}\nrule := {Attr: \"weight\", Rule: \"number\", Min: 45, Max: 45} // == 45\nrule := {Attr: \"weight\", Rule: \"number\", Min: 45, Max: 49.9, Required: true}\n```\n\n### booleanValidator\n- 布尔，被验证字段支持类型 bool、string\n- Rule.Rule        string    必选    boolean/bool\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\n// bool 为 boolean 的别名，都指向 booleanValidator 验证器\nrule := {Attr: \"admin\", Rule: \"bool\"}\nrule := {Attr: \"admin\", Rule: \"boolean\"}\n\n// 布尔值[true、false]、字符串表示的布尔值[\"1\"、\"0\"、\"t\"、\"f\"、\"true\"、\"false\"(忽略大小写)] 都会被认为是布尔\n```\n\n### ipValidator\n- ipv4/ipv6，被验证字段支持类型 string\n- Rule.Rule        string    必选    ip\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\nrule := {Attr: \"ip\", Rule: \"ip\"}\n```\n\n### regexValidator\n- 正则，被验证字段支持类型 string\n- Rule.Rule        string    必选    regex\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n- Rule.Pattern     string    必选    正则模式字符串\n```go\nrule := {Attr: \"password\", Rule: \"regex\", Pattern: `[A-Z]{1}\\w{5,}`},\n```\n\n### emailValidator\n- email，被验证字段支持类型 string\n- Rule.Rule        string    必选    email\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\nrule := {Attr: \"email\", Rule: \"email\"}\n\n// pattern = `^[\\w!#$%\u0026'*+/=?^_` + \"`\" + `{|}~-]+(?:\\.[\\w!#$%\u0026'*+/=?^_` + \"`\" + `{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?$`\n```\n\n### telValidator\n- 中国大陆座机号，被验证字段支持类型 string\n- Rule.Rule        string    必选    tel\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\nrule := {Attr: \"tel\", Rule: \"tel\"}\n\n// pattern = `^(0\\d{2,3}(\\-)?)?\\d{7,8}$`\n```\n\n### mobileValidator\n- 中国大陆手机号，被验证字段支持类型 string\n- Rule.Rule        string    必选    mobile\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\nrule := {Attr: \"mobile\", Rule: \"mobile\"}\n\n// pattern = `^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][01356789]|[4][579]))\\d{8}$`\n```\n\n### zipcodeValidator\n- 中国大陆邮编，被验证字段支持类型 string\n- Rule.Rule        string    必选    zipcode\n- Rule.Required    bool      可选    false(默认) - 被验证字段有值验证/无值跳过，true - 被验证字段无值，验证失败，报 reqired 错误\n```go\nrule := {Attr: \"zipcode\", Rule: \"zipcode\"}\n\n// pattern = `^[1-9]\\d{5}$`\n```\n\n## 自动验证\n- 本例以 beego 框架为例，扩展其 model，实现自动验证，使用常见的 base model/controller 模式，为子类提供统一方法\n\n### base/BaseController\n```go\npackage base\n\nimport (\n    \"encoding/json\"\n    \"github.com/astaxie/beego\"\n)\n\ntype JSON struct {\n    Code      int64          `json:\"code\"`      \n    Data      interface{}    `json:\"data\"`\n    Errors    interface{}    `json:\"errors\"`\n}\n\ntype BaseController struct {\n    beego.Controller\n}\n\nfunc (this *BaseController) LoadJson() (beego.M, error){\n    var js beego.M\n    return js, json.Unmarshal(this.Ctx.Input.RequestBody, \u0026js)\n}\n\nfunc (this *BaseController) ReturnJson(code int64, data interface{}, e interface{}) {\n    this.Data[\"json\"] = \u0026JSON{\n        Code: code,\n        Data: data,\n        Errors: e,\n    }\n    this.ServeJSON()\n}\n```\n\n### base/BaseModel\n```go\npackage base\n\nimport (\n    \"reflect\"\n    \"github.com/goindow/validator\"\n)\n\n// 为了避免每个子 model 文件都要写 import validator，在这里定义几个变量别名，供子 model 直接使用\ntype E = validator.E\ntype M = validator.M\ntype Rule = validator.Rule\ntype Rules = validator.Rules\ntype Scence = validator.Scence\n\ntype BaseModel struct {}\n\n// 定义验证规则\nfunc (this *BaseModel) Rules() Rules{\n    return nil\n}\n\n// 自动验证\nfunc (this *BaseModel) Validate(ptrChildModel interface{}, js map[string]interface{}, scence Scence) []E {\n    // 获取 ptrChildModel 的 Rules\n    if rules := reflect.ValueOf(ptrChildModel).MethodByName(\"Rules\").Call(make([]reflect.Value, 0))[0].Interface().(Rules); len(rules) != 0 {\n        return validator.New().Validate(rules, js, scence)      \n    }\n    return nil\n}\n```\n\n### models/User\n```go\npackage models\n\nimport (\n    \"explore/base\"\n)\n\ntype User struct {\n    base.BaseModel\n    Id          int64\n    Username    string\n    Password    string\n}\n\nfunc (this *User) Rules() base.Rules {\n    return base.Rules{\n        \"signup\": {\n            {Attr: []string{\"username\", \"password\", \"rpassword\"}, Rule: \"required\"},\n            {Attr: \"username\", Rule: \"string\"},\n            {Attr: \"password\", Rule: \"regex\", Pattern: `[a-zA-Z].\\d{5,}`},\n            {Attr: \"rpassword\", Rule: \"func\", Func: func(attr string, rule base.Rule, obj base.M) base.E {\n                if obj[\"password\"] != obj[\"rpassword\"] {\n                    return base.E{attr: \"两次输入不一致\"}\n                }\n                return nil\n            }},\n        },\n        \"signin\": {\n            {Attr: []string{\"username\", \"password\"}, Rule: \"required\"},\n            {Attr: \"password\", Rule: \"func\", Func: func(attr string, rule base.Rule, obj base.M) base.E {\n                if obj[\"username\"] != \"admin\" || obj[\"password\"] != \"admin\" {\n                    return base.E{attr: \"用户名或密码错误\"}\n                }\n                return nil\n            }},\n        },\n    }\n}\n```\n\n### controllers/UserController\n```go\npackage controllers\n\nimport (\n    \"explore/base\"\n    \"explore/models\"\n)\n\ntype UserController struct {\n    base.BaseController\n}\n\n// @router /signup [post]\nfunc (this *UserController) Signup() {\n    if js, err := this.LoadJson(); err != nil {\n        this.ReturnJson(4000, nil, \"Json 解析失败\")\n    } else {\n        var user models.User\n        if e := user.Validate(\u0026user, js, \"signup\"); len(e) != 0 {\n            this.ReturnJson(3000, nil, e)\n        } else {\n            // todo:\n            this.ReturnJson(2000, nil, \"注册成功\")\n        }\n    }\n}\n\n// @router /signin [post]\nfunc (this *UserController) Signin() {\n    if js, err := this.LoadJson(); err != nil {\n        this.ReturnJson(4000, nil, \"Json 解析失败\")\n    } else {\n        var user models.User\n        if e := user.Validate(\u0026user, js, \"signin\"); len(e) != 0 {\n            this.ReturnJson(3001, nil, e)\n        } else {\n            // todo:\n            this.ReturnJson(2000, nil, \"登陆成功\")\n        }\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoindow%2Fvalidator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoindow%2Fvalidator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoindow%2Fvalidator/lists"}