Documentにはなかったので、ソースコードを読んでこうしてみました。
検証用の関数を作る
以下のように検証用の関数を作ります。
package myvalidator
import (
"gopkg.in/go-playground/validator.v8"
"reflect"
)
var MyValidations = map[string]validator.Func {
"custom1": custom1,
"custom2": custom2,
}
func Custom1(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
if fieldKind == reflect.String {
str := field.String()
// 検証が通ればtrueを返す
return true
} else {
return false
}
}
func Custom2(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
if fieldKind == reflect.String {
str := field.String()
// 検証が通ればtrueを返す
return true
} else {
return false
}
}
CustomValidatorを作る(検証関数の登録)
ginのbinding/default_validator.goを参考にしてValidatorを作る
package myvalidator
import (
"sync"
"gopkg.in/go-playground/validator.v8"
"reflect"
)
type MyValidator struct {
once sync.Once
validate *validator.Validate
}
func (v *MyValidator) ValidateStruct(obj interface{}) error {
if kindOfData(obj) == reflect.Struct {
v.lazyinit()
if err := v.validate.Struct(obj); err != nil {
return error(err)
}
}
return nil
}
func (v *MyValidator) lazyinit() {
v.once.Do(func() {
config := &validator.Config{TagName: "binding"}
// ここにrequiredなど元からあるValidationは含まれている
v.validate = validator.New(config)
// ここでValidation関数を登録
for key, value := range MyValidations {
v.validate.RegisterValidation(key, value)
}
})
}
func kindOfData(data interface{}) reflect.Kind {
value := reflect.ValueOf(data)
valueType := value.Kind()
if valueType == reflect.Ptr {
valueType = value.Elem().Kind()
}
return valueType
}
ginに作ったValidatorを設定
import (
"github.com/gin-gonic/gin"
)
// gin.Default()を呼ぶ前に呼んで、ginのValidatorを初期化する
func initGinValidator() {
binding.Validator = &myvalidator.MyValidations{}
}