乐观积极的现实理想的 發表於 2021-8-18 16:11:00

Go语言参数校验(go-playground / validator)——基本使用

<p>Go语言没有像Java一样的注解快速进行参数的校验,但可以通过struct tag(结构体标签)进行序列化。常用的如:</p>
<p>type User struct {<br>        ID string `json:"id"`<br>        Name string `json:"name"`<br>        Age string `json:"age"`<br>} <br>但需要更复杂的校验,这时需要用一些专业的库来完成。go-playground / validator作为一款优秀的Go语言校验库,基于标记为结构体和单个字段实现值验证。使用简单、快捷。</p>
<p>添加依赖<br>go get github.com/go-playground/validator<br>代码<br>package main<br> <br>import (<br>        "fmt"<br>        "github.com/go-playground/validator"<br>)<br> <br>var validate *validator.Validate //定义<br> <br>type User struct {<br>        Namestring `validate:"required"` //非空<br>        Age   uint8`validate:"gte=0,lte=130"` //0&lt;=Age&lt;=130<br>        Email string `validate:"required,email"` //非空,email格式<br>        //dive关键字代表 进入到嵌套结构体进行判断<br>        Address []*Address `validate:"dive"` //可以拥有多个地址<br>}<br>type Address struct {<br>        Province string `validate:"required"` //非空<br>        City   string `validate:"required"` //非空<br>        Phone    string `validate:"numeric,len=11"` //数字类型,长度为11<br>}<br> <br>func main() {<br>        validate = validator.New() //初始化(赋值)<br>        validateStruct()         //结构体校验<br>        validateVariable()         //变量校验<br>}<br>func validateStruct() {<br>        address := Address{<br>                Province: "重庆",<br>                City:   "重庆",<br>                Phone:    "13366663333x",<br>        }<br>        user := User{<br>                Name:"江洲",<br>                Age:   23,<br>                Email: "jz@163.com",<br>                Address: []*Address{&amp;address},<br>        }<br>        err := validate.Struct(user)<br>        if err != nil {<br>                //断言为:validator.ValidationErrors,类型为:[]FieldError<br>                for _, e := range err.(validator.ValidationErrors) {<br>                        fmt.Println("Namespace:", e.Namespace())<br>                        fmt.Println("Field:", e.Field())<br>                        fmt.Println("StructNamespace:", e.StructNamespace())<br>                        fmt.Println("StructField:", e.StructField())<br>                        fmt.Println("Tag:", e.Tag())<br>                        fmt.Println("ActualTag:", e.ActualTag())<br>                        fmt.Println("Kind:", e.Kind())<br>                        fmt.Println("Type:", e.Type())<br>                        fmt.Println("Value:", e.Value())<br>                        fmt.Println("Param:", e.Param())<br>                        fmt.Println()<br>                }<br> <br>                fmt.Println("结构体输入数据类型错误!")<br>                return<br>        } else {<br>                fmt.Println("结构体校验通过")<br>        }<br>}<br>//变量校验<br>func validateVariable() {<br>        myEmail := "123@qq.com" //邮箱地址:xx@xx.com<br>        err := validate.Var(myEmail, "required,email")<br>        if err != nil {<br>                fmt.Println(err)<br>        } else {<br>                fmt.Println("变量校验通过!")<br>        }<br>}<br>运行效果:</p>
<p><br>————————————————<br>版权声明:本文为CSDN博主「cqu_jiangzhou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。<br>原文链接:https://blog.csdn.net/weixin_42117918/article/details/107407053</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 id="item-0-1">前言</h3>
<p>在web应用中经常会遇到数据验证问题,普通的验证方法比较繁琐,这里介绍一个使用比较多的包validator。</p>
<h3 id="item-0-2">原理</h3>
<p>将验证规则写在struct对字段tag里,再通过反射(reflect)获取struct的tag,实现数据验证。</p>
<p>安装</p>
<pre class="hljs language-vim"><span class="hljs-keyword">go <span class="hljs-built_in">get github.<span class="hljs-keyword">com/<span class="hljs-keyword">go-playground/validator/v10</span></span></span></span></pre>
<p>示例</p>
<pre class="hljs language-pgsql">package main

<span class="hljs-keyword">import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

<span class="hljs-keyword">type Users struct {
    Phone   string `form:"phone" <span class="hljs-type">json:"phone" <span class="hljs-keyword">validate:"required"`
    Passwd   string `form:"passwd" <span class="hljs-type">json:"passwd" <span class="hljs-keyword">validate:"required,max=20,min=6"`
    Code   string `form:"code" <span class="hljs-type">json:"code" <span class="hljs-keyword">validate:"required,len=6"`
}

func main() {

    users := &amp;Users{
      Phone:      "1326654487",
      Passwd:       "123",
      Code:            "123456",
    }
    <span class="hljs-keyword">validate := <span class="hljs-keyword">validator.<span class="hljs-built_in">New()
    err := <span class="hljs-keyword">validate.Struct(users)
    <span class="hljs-keyword">if err != nil {
      <span class="hljs-keyword">for _, err := range err.(<span class="hljs-keyword">validator.ValidationErrors) {
            fmt.Println(err)//Key: <span class="hljs-string">'Users.Passwd' Error:Field validation <span class="hljs-keyword">for <span class="hljs-string">'Passwd' failed <span class="hljs-keyword">on the <span class="hljs-string">'min' tag
            <span class="hljs-keyword">return
      }
    }
    <span class="hljs-keyword">return
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<h3 id="item-0-3">验证规则</h3>
<ul>
<li>required :必填</li>
<li>email:验证字符串是email格式;例:"email"</li>
<li>url:这将验证字符串值包含有效的网址;例:"url"</li>
<li>max:字符串最大长度;例:"max=20"</li>
<li>min:字符串最小长度;例:"min=6"</li>
<li>excludesall:不能包含特殊字符;例:"excludesall=0x2C"//注意这里用十六进制表示。</li>
<li>len:字符长度必须等于n,或者数组、切片、map的len值为n,即包含的项目数;例:"len=6"</li>
<li>eq:数字等于n,或者或者数组、切片、map的len值为n,即包含的项目数;例:"eq=6"</li>
<li>ne:数字不等于n,或者或者数组、切片、map的len值不等于为n,即包含的项目数不为n,其和eq相反;例:"ne=6"</li>
<li>gt:数字大于n,或者或者数组、切片、map的len值大于n,即包含的项目数大于n;例:"gt=6"</li>
<li>gte:数字大于或等于n,或者或者数组、切片、map的len值大于或等于n,即包含的项目数大于或等于n;例:"gte=6"</li>
<li>lt:数字小于n,或者或者数组、切片、map的len值小于n,即包含的项目数小于n;例:"lt=6"</li>
<li>lte:数字小于或等于n,或者或者数组、切片、map的len值小于或等于n,即包含的项目数小于或等于n;例:"lte=6"</li>
</ul>
<h4>跨字段验证</h4>
<p>如想实现比较输入密码和确认密码是否一致等类似场景</p>
<ul>
<li><code>eqfield=Field</code>: 必须等于 Field 的值;</li>
<li><code>nefield=Field</code>: 必须不等于 Field 的值;</li>
<li><code>gtfield=Field</code>: 必须大于 Field 的值;</li>
<li><code>gtefield=Field</code>: 必须大于等于 Field 的值;</li>
<li><code>ltfield=Field</code>: 必须小于 Field 的值;</li>
<li><code>ltefield=Field</code>: 必须小于等于 Field 的值;</li>
<li><code>eqcsfield=Other.Field</code>: 必须等于 struct Other 中 Field 的值;</li>
<li><code>necsfield=Other.Field</code>: 必须不等于 struct Other 中 Field 的值;</li>
<li><code>gtcsfield=Other.Field</code>: 必须大于 struct Other 中 Field 的值;</li>
<li><code>gtecsfield=Other.Field</code>: 必须大于等于 struct Other 中 Field 的值;</li>
<li><code>ltcsfield=Other.Field</code>: 必须小于 struct Other 中 Field 的值;</li>
<li><code>ltecsfield=Other.Field</code>: 必须小于等于 struct Other 中 Field 的值;</li>
</ul>
<p>示例</p>
<pre class="hljs language-pgsql"><span class="hljs-keyword">type UserReg struct {
    Passwd   string `form:"passwd" <span class="hljs-type">json:"passwd" <span class="hljs-keyword">validate:"required,max=20,min=6"`
    Repasswd   string `form:"repasswd" <span class="hljs-type">json:"repasswd" <span class="hljs-keyword">validate:"required,max=20,min=6,eqfield=Passwd"`
}</span></span></span></span></span></pre>
<p>示例验证了Passwd,和Repasswd值是否相等。如想了解更多类型,请参考文档&nbsp;https://godoc.org/gopkg.in/go...</p>
<h3 id="item-0-4">自定义验证类型</h3>
<p>示例:</p>
<pre class="hljs language-pgsql">package main

<span class="hljs-keyword">import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

<span class="hljs-keyword">type Users struct {
    <span class="hljs-type">Name   string `form:"name" <span class="hljs-type">json:"name" <span class="hljs-keyword">validate:"required,CustomValidationErrors"`//包含自定义函数
    Age   uint8 `form:"age" <span class="hljs-type">json:"age" <span class="hljs-keyword">validate:"required,gt=18"`
    Passwd   string `form:"passwd" <span class="hljs-type">json:"passwd" <span class="hljs-keyword">validate:"required,max=20,min=6"`
    Code   string `form:"code" <span class="hljs-type">json:"code" <span class="hljs-keyword">validate:"required,len=6"`
}

func main() {

    users := &amp;Users{
      <span class="hljs-type">Name:      "admin",
      Age:      <span class="hljs-number">12,
      Passwd:       "123",
      Code:            "123456",
    }
    <span class="hljs-keyword">validate := <span class="hljs-keyword">validator.<span class="hljs-built_in">New()
    //注册自定义函数
    _=<span class="hljs-keyword">validate.RegisterValidation("CustomValidationErrors", CustomValidationErrors)
    err := <span class="hljs-keyword">validate.Struct(users)
    <span class="hljs-keyword">if err != nil {
      <span class="hljs-keyword">for _, err := range err.(<span class="hljs-keyword">validator.ValidationErrors) {
            fmt.Println(err)//Key: <span class="hljs-string">'Users.Name' Error:Field validation <span class="hljs-keyword">for <span class="hljs-string">'Name' failed <span class="hljs-keyword">on the <span class="hljs-string">'CustomValidationErrors' tag
            <span class="hljs-keyword">return
      }
    }
    <span class="hljs-keyword">return
}

func CustomValidationErrors(fl <span class="hljs-keyword">validator.FieldLevel) <span class="hljs-type">bool {
<span class="hljs-keyword">return fl.Field().String() != "admin"
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<h3 id="item-0-5">翻译错误信息为中文</h3>
<p>通过以上示例我们看到,validator默认的错误提示信息类似如下</p>
<pre class="hljs language-sas"><span class="hljs-keyword">Key: <span class="hljs-string">'Users.Name' <span class="hljs-keyword">Error:Field validation for <span class="hljs-string">'Name' failed <span class="hljs-keyword">on the <span class="hljs-string">'CustomValidationErrors' tag</span></span></span></span></span></span></pre>
<p>显然这并不是我们想要,如想翻译成中文,或其他语言怎么办?go-playground上提供了很好的解决方法。</p>
<p>先自行安装需要的两个包</p>
<p>https://github.com/go-playground/locales<br>https://github.com/go-playground/universal-translator</p>
<p>执行:</p>
<pre class="hljs language-vim"><span class="hljs-keyword">go <span class="hljs-built_in">get github.<span class="hljs-keyword">com/<span class="hljs-keyword">go-playground/universal-translator
<span class="hljs-keyword">go <span class="hljs-built_in">get github.<span class="hljs-keyword">com/<span class="hljs-keyword">go-playground/locales</span></span></span></span></span></span></span></span></pre>
<p>示例:</p>
<pre class="hljs language-pgsql">package main

<span class="hljs-keyword">import (
    "fmt"
    "github.com/go-playground/locales/zh"
    ut "github.com/go-playground/universal-translator"
    "github.com/go-playground/validator/v10"
    zh_translations "github.com/go-playground/validator/v10/translations/zh"
)

<span class="hljs-keyword">type Users struct {
    <span class="hljs-type">Name   string `form:"name" <span class="hljs-type">json:"name" <span class="hljs-keyword">validate:"required"`
    Age   uint8 `form:"age" <span class="hljs-type">json:"age" <span class="hljs-keyword">validate:"required,gt=18"`
    Passwd   string `form:"passwd" <span class="hljs-type">json:"passwd" <span class="hljs-keyword">validate:"required,max=20,min=6"`
    Code   string `form:"code" <span class="hljs-type">json:"code" <span class="hljs-keyword">validate:"required,len=6"`
}

func main() {
    users := &amp;Users{
      <span class="hljs-type">Name:      "admin",
      Age:      <span class="hljs-number">12,
      Passwd:       "123",
      Code:            "123456",
    }
    uni := ut.<span class="hljs-built_in">New(zh.<span class="hljs-built_in">New())
    trans, _ := uni.GetTranslator("zh")
    <span class="hljs-keyword">validate := <span class="hljs-keyword">validator.<span class="hljs-built_in">New()
    //验证器注册翻译器
    err := zh_translations.RegisterDefaultTranslations(<span class="hljs-keyword">validate, trans)
    <span class="hljs-keyword">if err!=nil {
      fmt.Println(err)
    }
    err = <span class="hljs-keyword">validate.Struct(users)
    <span class="hljs-keyword">if err != nil {
      <span class="hljs-keyword">for _, err := range err.(<span class="hljs-keyword">validator.ValidationErrors) {
            fmt.Println(err.Translate(trans))//Age必须大于<span class="hljs-number">18
            <span class="hljs-keyword">return
      }
    }

    <span class="hljs-keyword">return
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>输出:</p>
<pre class="hljs language-apache"><span class="hljs-attribute">Age必须大于<span class="hljs-number">18</span></span></pre>
<p>至此我们发现大部分错误信息已经翻译成中文,但字段名(Age)还是没有翻译,为了将字段名翻译成中文,查了一些资料,https://www.jianshu.com/p/51b...,</p>
<p>照着做没有成功(可能有遗漏吧),最后还是翻看了一下源代码,在https://github.com/go-playgro...,第137行</p>
<pre class="hljs language-awk"><span class="hljs-regexp">// RegisterTagNameFunc registers a <span class="hljs-keyword">function to get alternate names <span class="hljs-keyword">for StructFields.
<span class="hljs-regexp">//
<span class="hljs-regexp">// eg. to use the names which have been specified <span class="hljs-keyword">for JSON representations of structs, rather than normal Go field names:
<span class="hljs-regexp">//
<span class="hljs-regexp">//    validate.RegisterTagNameFunc(<span class="hljs-keyword">func(fld reflect.StructField) string {
<span class="hljs-regexp">//      name := strings.SplitN(fld.Tag.Get(<span class="hljs-string">"json"), <span class="hljs-string">",", <span class="hljs-number">2)[<span class="hljs-number">0]
<span class="hljs-regexp">//      <span class="hljs-keyword">if name == <span class="hljs-string">"-" {
<span class="hljs-regexp">//            return <span class="hljs-string">""
<span class="hljs-regexp">//      }
<span class="hljs-regexp">//      return name
<span class="hljs-regexp">//    })</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>其实原理就是注册一个函数,将struct tag里添加的中文名 作为备用名。</p>
<pre class="hljs language-pgsql">package main

<span class="hljs-keyword">import (
    "fmt"
    "github.com/go-playground/locales/zh"
    ut "github.com/go-playground/universal-translator"
    "github.com/go-playground/validator/v10"
    zh_translations "github.com/go-playground/validator/v10/translations/zh"
    "reflect"
)

<span class="hljs-keyword">type Users struct {
    <span class="hljs-type">Name   string `form:"name" <span class="hljs-type">json:"name" <span class="hljs-keyword">validate:"required" label:"用户名"`
    Age   uint8 `form:"age" <span class="hljs-type">json:"age" <span class="hljs-keyword">validate:"required,gt=18" label:"年龄"`
    Passwd   string `form:"passwd" <span class="hljs-type">json:"passwd" <span class="hljs-keyword">validate:"required,max=20,min=6"`
    Code   string `form:"code" <span class="hljs-type">json:"code" <span class="hljs-keyword">validate:"required,len=6"`
}

func main() {
    users := &amp;Users{
      <span class="hljs-type">Name:      "admin",
      Age:      <span class="hljs-number">12,
      Passwd:       "123",
      Code:            "123456",
    }
    uni := ut.<span class="hljs-built_in">New(zh.<span class="hljs-built_in">New())
    trans, _ := uni.GetTranslator("zh")
    <span class="hljs-keyword">validate := <span class="hljs-keyword">validator.<span class="hljs-built_in">New()
    //注册一个函数,获取struct tag里自定义的label作为字段名
    <span class="hljs-keyword">validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
      <span class="hljs-type">name:=fld.Tag.<span class="hljs-keyword">Get("label")
      <span class="hljs-keyword">return <span class="hljs-type">name
    })
    //注册翻译器
    err := zh_translations.RegisterDefaultTranslations(<span class="hljs-keyword">validate, trans)
    <span class="hljs-keyword">if err!=nil {
      fmt.Println(err)
    }
    err = <span class="hljs-keyword">validate.Struct(users)
    <span class="hljs-keyword">if err != nil {
      <span class="hljs-keyword">for _, err := range err.(<span class="hljs-keyword">validator.ValidationErrors) {
            fmt.Println(err.Translate(trans))//年龄必须大于<span class="hljs-number">18
            <span class="hljs-keyword">return
      }
    }

    <span class="hljs-keyword">return
}

</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>输出结果:</p>
<pre class="hljs language-undefined">年龄必须大于18</pre>
<h3 id="item-0-6">gin 内置的validator</h3>
<p>gin已经支持go-playground / validator / v10进行验证。在此处查看有关标签用法的完整文档。</p>
<p>以下只提供了一个绑定ShouldBindWith示例,如需了解更多方法,进入这里。</p>
<p>示例</p>
<pre class="hljs language-go"><span class="hljs-keyword">package main

<span class="hljs-keyword">import (
    <span class="hljs-string">"fmt"
    <span class="hljs-string">"github.com/go-playground/locales/zh"
    ut <span class="hljs-string">"github.com/go-playground/universal-translator"
    <span class="hljs-string">"github.com/go-playground/validator/v10"
    <span class="hljs-string">"net/http"
    <span class="hljs-string">"reflect"
    <span class="hljs-string">"strings"
    <span class="hljs-string">"time"

    <span class="hljs-string">"github.com/gin-gonic/gin"
    <span class="hljs-string">"github.com/gin-gonic/gin/binding"
    zh_translations <span class="hljs-string">"github.com/go-playground/validator/v10/translations/zh"
)
<span class="hljs-keyword">var trans ut.Translator
<span class="hljs-comment">// Booking contains binded and validated data.
<span class="hljs-keyword">type Booking <span class="hljs-keyword">struct {
    CheckIntime.Time <span class="hljs-string">`form:"check_in" json:"check_in" binding:"required,bookabledate" time_format:"2006-01-02" label:"输入时间"`
    CheckOut time.Time <span class="hljs-string">`form:"check_out" json:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02" label:"输出时间"`
}

<span class="hljs-keyword">var bookableDate validator.Func = <span class="hljs-function"><span class="hljs-keyword">func<span class="hljs-params">(fl validator.FieldLevel) <span class="hljs-title">bool {
    date, ok := fl.Field().Interface().(time.Time)
    <span class="hljs-keyword">if ok {
      today := time.Now()
      <span class="hljs-keyword">if today.After(date) {
            <span class="hljs-keyword">return <span class="hljs-literal">false
      }
    }
    <span class="hljs-keyword">return <span class="hljs-literal">true
}

<span class="hljs-function"><span class="hljs-keyword">func <span class="hljs-title">main<span class="hljs-params">() {
    route := gin.Default()
    uni := ut.New(zh.New())
    trans, _ = uni.GetTranslator(<span class="hljs-string">"zh")

    <span class="hljs-keyword">if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
      <span class="hljs-comment">//注册翻译器
      _= zh_translations.RegisterDefaultTranslations(v, trans)
      <span class="hljs-comment">//注册自定义函数
      _=v.RegisterValidation(<span class="hljs-string">"bookabledate", bookableDate)

      <span class="hljs-comment">//注册一个函数,获取struct tag里自定义的label作为字段名
      v.RegisterTagNameFunc(<span class="hljs-function"><span class="hljs-keyword">func<span class="hljs-params">(fld reflect.StructField) <span class="hljs-title">string {
            name:=fld.Tag.Get(<span class="hljs-string">"label")
            <span class="hljs-keyword">return name
      })
      <span class="hljs-comment">//根据提供的标记注册翻译
      v.RegisterTranslation(<span class="hljs-string">"bookabledate", trans, <span class="hljs-function"><span class="hljs-keyword">func<span class="hljs-params">(ut ut.Translator) <span class="hljs-title">error {
            <span class="hljs-keyword">return ut.Add(<span class="hljs-string">"bookabledate", <span class="hljs-string">"{0}不能早于当前时间或{1}格式错误!", <span class="hljs-literal">true)
      }, <span class="hljs-function"><span class="hljs-keyword">func<span class="hljs-params">(ut ut.Translator, fe validator.FieldError) <span class="hljs-title">string {
            t, _ := ut.T(<span class="hljs-string">"bookabledate", fe.Field(), fe.Field())
            <span class="hljs-keyword">return t
      })

    }
    route.GET(<span class="hljs-string">"/bookable", getBookable)
    route.Run(<span class="hljs-string">":8085")
}

<span class="hljs-function"><span class="hljs-keyword">func <span class="hljs-title">getBookable<span class="hljs-params">(c *gin.Context) {
    <span class="hljs-keyword">var b Booking
    <span class="hljs-keyword">if err := c.ShouldBindWith(&amp;b, binding.Query); err == <span class="hljs-literal">nil {
      c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"message": <span class="hljs-string">"Booking dates are valid!"})
    } <span class="hljs-keyword">else {
      errs := err.(validator.ValidationErrors)

      fmt.Println(errs.Translate(trans))
      <span class="hljs-comment">//for _, e := range errs {
      <span class="hljs-comment">//    // can translate each error one at a time.
      <span class="hljs-comment">//    fmt.Println(e.Translate(trans))
      <span class="hljs-comment">//}
      c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"error": errs.Translate(trans)})
    }
}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>运行程序,执行以下命令</p>
<pre class="hljs language-subunit">$ curl "localhost:8085/bookable?check_in=2018<span class="hljs-string">-04<span class="hljs-string">-16&amp;check_out=2018<span class="hljs-string">-04<span class="hljs-string">-16"</span></span></span></span></pre>
<p>结果:</p>
<pre class="hljs language-json"><span class="hljs-punctuation">{<span class="hljs-attr">"error"<span class="hljs-punctuation">:<span class="hljs-punctuation">{<span class="hljs-attr">"Booking.输入时间"<span class="hljs-punctuation">:<span class="hljs-string">"输入时间不能早于当前时间或输入时间格式错误!"<span class="hljs-punctuation">,<span class="hljs-attr">"Booking.输出时间"<span class="hljs-punctuation">:<span class="hljs-string">"输出时间必须大于CheckIn"<span class="hljs-punctuation">}<span class="hljs-punctuation">}</span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>查看以上结果我们发现翻译还是不太完美,如规则中有gtfield的情况,字段(CheckIn)并没有被翻译。所以通过struct添加label的方式并不能从根本上解决字段翻译问题。为了得到想要的结果,就需要将错误信息做单独处理再输出。</p>
<p>先定义翻译库</p>
<pre class="hljs language-go"><span class="hljs-keyword">var BookingTrans =<span class="hljs-keyword">map[<span class="hljs-keyword">string]<span class="hljs-keyword">string{<span class="hljs-string">"CheckIn":<span class="hljs-string">"输入时间",<span class="hljs-string">"CheckOut":<span class="hljs-string">"输出时间"}</span></span></span></span></span></span></span></span></pre>
<p>再定义翻译函数</p>
<pre class="hljs language-go"><span class="hljs-function"><span class="hljs-keyword">func <span class="hljs-title">TransTagName<span class="hljs-params">(libTans,err <span class="hljs-keyword">interface{}) <span class="hljs-title">interface{} {
    <span class="hljs-keyword">switch err.(<span class="hljs-keyword">type) {
    <span class="hljs-keyword">case validator.ValidationErrorsTranslations:
      <span class="hljs-keyword">var errs <span class="hljs-keyword">map[<span class="hljs-keyword">string]<span class="hljs-keyword">string
      errs = <span class="hljs-built_in">make(<span class="hljs-keyword">map[<span class="hljs-keyword">string]<span class="hljs-keyword">string,<span class="hljs-number">0)
      <span class="hljs-keyword">for k,v:=<span class="hljs-keyword">range err.(validator.ValidationErrorsTranslations){
            <span class="hljs-keyword">for key,value:=<span class="hljs-keyword">range libTans.(<span class="hljs-keyword">map[<span class="hljs-keyword">string]<span class="hljs-keyword">string){
                v=strings.Replace(v,key,value,<span class="hljs-number">-1)
            }
            errs = v
      }
      <span class="hljs-keyword">return errs
    <span class="hljs-keyword">case <span class="hljs-keyword">string:
      <span class="hljs-keyword">var errs <span class="hljs-keyword">string
      <span class="hljs-keyword">for key,value:=<span class="hljs-keyword">range libTans.(<span class="hljs-keyword">map[<span class="hljs-keyword">string]<span class="hljs-keyword">string){
            errs=strings.Replace(errs,key,value,<span class="hljs-number">-1)
      }
      <span class="hljs-keyword">return errs
    <span class="hljs-keyword">default:
      <span class="hljs-keyword">return err
    }
}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p>将原来翻译错误信息的地方</p>
<pre class="hljs language-reasonml">errs.<span class="hljs-constructor">Translate(<span class="hljs-params">trans)</span></span></pre>
<p>修改为</p>
<pre class="hljs language-css">msg:=<span class="hljs-built_in">TransTagName(BookingTrans,errs.<span class="hljs-built_in">Translate(trans))
fmt.<span class="hljs-built_in">Println(msg)</span></span></span></pre>
<p>结果</p>
<pre class="hljs language-json"><span class="hljs-punctuation">{<span class="hljs-attr">"error"<span class="hljs-punctuation">:<span class="hljs-punctuation">{<span class="hljs-attr">"Booking.输入时间"<span class="hljs-punctuation">:<span class="hljs-string">"输入时间不能早于当前时间或输入时间格式错误!"<span class="hljs-punctuation">,<span class="hljs-attr">"Booking.输出时间"<span class="hljs-punctuation">:<span class="hljs-string">"输出时间必须大于输入时间"<span class="hljs-punctuation">}<span class="hljs-punctuation">}</span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<h3 id="item-0-7">小结:</h3>
<ol>
<li>gin 已经支持validator最新的v10。</li>
<li>validator数据验证顺序struct字段从上往下,单个字段规则(binding:"gt=0,lt=2`),先左后右。</li>
</ol>
<p>参考:</p>
<p>https://github.com/go-playgro...</p>
<p>https://github.com/gin-gonic/gin</p>
<p>https://gitissue.com/issues/5...</p>
<p>https://segmentfault.com/a/11...</p><br><br>
来源:https://www.cnblogs.com/ExMan/p/15157303.html
頁: [1]
查看完整版本: Go语言参数校验(go-playground / validator)——基本使用