Skip to content

Instantly share code, notes, and snippets.

@reiki4040
Created December 1, 2014 14:47
Show Gist options
  • Save reiki4040/19443b835c910f658b37 to your computer and use it in GitHub Desktop.
Save reiki4040/19443b835c910f658b37 to your computer and use it in GitHub Desktop.
validation memo
package main
import (
"errors"
"fmt"
"net/url"
"reflect"
"strconv"
"strings"
)
type Validator interface {
Validate() []error
}
type Binder interface {
Bind(params url.Values) []error
}
type BindHelper struct {
helper ValidationHelper
}
func (b *BindHelper) Bind(params url.Values, binder Binder) []error {
return nil
}
type ValidationHelper struct {
Message string
}
func (v *ValidationHelper) Valid() error {
return nil
}
func Validate(target interface{}, params *url.Values) []error {
t := reflect.TypeOf(target)
v := reflect.ValueOf(target)
// if pointer get value
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
if t.Kind() != reflect.Struct {
return []error{errors.New("not struct given")}
}
fcount := t.NumField()
errs := make([]error, 0, 3)
for i := 0; i < fcount; i++ {
tf := t.Field(i)
required := tf.Tag.Get("required")
typeCheck := tf.Tag.Get("type")
opt := tf.Tag.Get("opt")
fmt.Printf("%s, %s, %s\n", required, typeCheck, opt)
lowerName := strings.ToLower(tf.Name)
pValue := params.Get(lowerName)
if required == "yes" {
if pValue == "" {
errs = append(errs, errors.New("is required."))
}
}
min := 1
max := 10
vf := v.Field(i)
switch typeCheck {
case "int":
validValue, err := IntValidate(lowerName, pValue, min, max)
if err != nil {
errs = append(errs, err)
} else {
x := int64(validValue)
if !vf.OverflowInt(x) {
vf.SetInt(x)
}
}
case "str":
validValue, err := StrValidate(lowerName, pValue, min, max)
if err != nil {
errs = append(errs, err)
} else {
vf.SetString(validValue)
fmt.Println("str setted.")
}
}
}
return errs
}
func StrValidate(name, param string, min, max int) (string, error) {
length := len(param)
if length < min || max < length {
return "", errors.New(fmt.Sprintf("%s valid length: %d to %d.", name, min, max))
}
return param, nil
}
func IntValidate(name, param string, min, max int) (int, error) {
v, err := strconv.Atoi(param)
if err != nil {
return 0, err
}
if v < min || max < v {
return 0, errors.New(fmt.Sprintf("%s valid range: %d to %d.", name, min, max))
}
return v, nil
}
type UsersParam struct {
UserId string `required:"true" type:"str" opt:"userid" default:""`
UserCode string `required:"false" type:"str" opt:"code"`
UserName string `type:"str`
}
func (u *UsersParam) Bind(params url.Values) []error {
user_id := params.Get("user_id")
user_code := params.Get("user_code")
u.UserId = user_id
u.UserCode = user_code
return nil
}
func main() {
usersParam := UsersParam{UserId: "", UserCode: ""}
params := &url.Values{}
params.Set("userid", "uid value")
errs := Validate(&usersParam, params)
for _, err := range errs {
fmt.Println(err.Error())
}
fmt.Printf("setted values: %s, %s\n", usersParam.UserId, usersParam.UserCode)
errs = Validate(3, params)
for _, err := range errs {
fmt.Println(err.Error())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment