golang validator参数校验的实现

 更新时间:2020年10月21日 10:13:25   作者:darcyaf  
这篇文章主要介绍了golang validator参数校验的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

今天在改后台页面,参数校验错误时输出全是英文,使用着很难看懂到底时什么错了
故而决定去做i18n前端国际化. 改的时候踩了很多坑,故而记录一下,顺便记录以下查问题的方式。

效果

从原来的Title is required变为标题为必填字段

完成后的代码:

这里主要定义了初始化了一个中文的trans和Validate的变量,并对其做初始化
初始化主要做了以下事情:

注册了TagName函数
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
这个方法主要就是提供一个tag的解析器,返回一个Field替代的字符串
我自己是定义了一个label的tag用于替换

注册了validate的翻译函数
直接使用了原来提供的中文转换,对required等标签做对应的国际化

package service

import (
  zhongwen "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"
  "strings"
)

var Validate *validator.Validate
var trans ut.Translator

func init() {
  zh := zhongwen.New()
  uni := ut.New(zh, zh)
  trans, _ = uni.GetTranslator("zh")

  Validate = validator.New()
  Validate.RegisterTagNameFunc(func(field reflect.StructField) string {
    label := field.Tag.Get("label")
    if label == "" {
      return field.Name
    }
    return label
  })
  zh_translations.RegisterDefaultTranslations(Validate, trans)
}
func Translate(errs validator.ValidationErrors) string {
  var errList []string
  for _, e := range errs {
    // can translate each error one at a time.
    errList = append(errList,e.Translate(trans))
  }
  return strings.Join(errList,"|")
}

调用方式

type ArticlesPost struct {
  Title      string `json:"title" validate:"required,max=32,min=4" label:"标题"`
}
var ap ArticlePost
err = service.Validate.Struct(ap)
if err!=nil{
 errStr =Translate(errs)
 fmt.Sprintln(errStr)
}

思路

  • 最刚开始去百度查了,无果
  • 查了iris的文档,也无果
  • 去看了validate的文档,找到了universal-translator 这个包,可以初步将is required等样式改为必填字段
  • 还是没法将字段名映射成中文,google搜索到了How can I translate fieldName? #364这个issue,评论里给出了en.Add("MyField", "Field", false)的方式添加字段的映射,最后在alidate.RegisterTranslation注册required的时候,通过T方法转换成对应的中文fld, _ := ut.T(fe.Field()),考虑到要每次都注册Struct的字段,而且全局的同一个key肯定没法定义不同的值,弃用
  • 第一次想着是不是校验本身已经提供了对应的位置,看了interface,有些英文半知半解,没找到结果,放弃
  • 继续,想到是不是可以自定义tag,然后重写type TranslationFunc func(ut ut.Translator, fe FieldError) string 函数,想在这个翻译阶段,去动态过去struct中那个tag的值,这样就不会重复了.
  • 研究了这个函数的传参,FieldError中已经只剩下字段对应的数据了,无法获取到tag信息,差点已经想放弃了
  • 再次研究validator关于tag的函数

第一个是设置一个新的tag来替换validate,另一个的说明是注册一个方法来为结构体字段获取替换的名字

仔细看看说明,果然就是这个,在看看TagNameFunc的签名,参数是reflect.StructField,能够拿到tag等一系列信息

// TagNameFunc allows for adding of a custom tag name parser
type TagNameFunc func(field reflect.StructField) string
// SetTagName allows for changing of the default tag name of 'validate'
func (v *Validate) SetTagName(name string) {
  v.tagName = name
}

// RegisterTagNameFunc registers a function to get alternate names for StructFields.
//
// eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names:
//
//  validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
//    name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
//    if name == "-" {
//      return ""
//    }
//    return name
//  })
func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
  v.tagNameFunc = fn
  v.hasTagNameFunc = true
}

至此,终于找到了正确的解决方案

总结

在这里发现为了解决这个问题走了很多弯路,查了一大堆资料才发现甚至原来就有提供该功能。

发现自己的几个问题:

  • 英文不是很好,偶尔有些单词不认识,阻止了进一步发现问题,这里也突然想到,英语好一些确实可以在学编程这个路子上受益匪浅
  • 看文档不是很仔细,鄙人觉得大部分的编程问题都不是很高深,能读得懂错误是什么意思,然后去查查文档或者搜索引擎就能解决,另一个是大部分的编程文档还是英文好一些,细节性的东西在翻译的时候可能会被略掉。

到此这篇关于golang validator参数校验的实现的文章就介绍到这了,更多相关golang validator参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何go语言比较两个对象是否深度相同

    如何go语言比较两个对象是否深度相同

    这篇文章主要介绍了如何go语言比较两个对象是否深度相同,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • 学习使用Go反射的用法示例

    学习使用Go反射的用法示例

    这篇文章主要介绍了学习使用Go反射的用法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • 一文详解Go语言io.LimitedReader类型

    一文详解Go语言io.LimitedReader类型

    这篇文章主要为大家介绍了Go语言io.LimitedReader类型示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Go设计模式之享元模式讲解和代码示例

    Go设计模式之享元模式讲解和代码示例

    享元是一种结构型设计模式,它允许你在消耗少量内存的情况下支持大量对象,模式通过共享多个对象的部分状态来实现上述功能,换句话来说,享元会将不同对象的相同数据进行缓存以节省内存,本文就将通过代码示例给大家详细介绍一下享元模式
    2023-06-06
  • Go语言数据类型简单介绍

    Go语言数据类型简单介绍

    这篇文章主要介绍了Go语言数据类型简单介绍的相关资料,需要的朋友可以参考下
    2023-08-08
  • 如何将Golang数组slice转为逗号分隔的string字符串

    如何将Golang数组slice转为逗号分隔的string字符串

    这篇文章主要介绍了如何将Golang数组slice转为逗号分隔的string字符串问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Golang实现根据某个特定字段对结构体的顺序进行排序

    Golang实现根据某个特定字段对结构体的顺序进行排序

    这篇文章主要为大家详细介绍了Golang如何实现根据某个特定字段对结构体的顺序进行排序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • golang string、int、int64 float 互相转换方式

    golang string、int、int64 float 互相转换方式

    这篇文章主要介绍了golang string、int、int64 float 互相转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 浅析Golang中make和new的用法区别

    浅析Golang中make和new的用法区别

    在Go语言中,有两个比较雷同的内置函数,分别是new和make方法,二者都可以用来分配内存,那他们有什么区别呢?下面就跟随小编一起来学习一下吧
    2024-02-02
  • Go编程库Sync.Pool用法示例详解

    Go编程库Sync.Pool用法示例详解

    这篇文章主要为大家介绍了Go编程库Sync.Pool用法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12

最新评论