Skip to content

hexdigest/genval

 
 

Repository files navigation

genval GoDoc Build Status

Generates Validate() methods for all structs in package by tags

  • no reflection in generated code - it means fast
  • possibilities to override generated behavior
  • can be used as //go:generate genval pkg
  • Enum support

Installation

go get github.com/gojuno/genval

Usage

type User struct {
    Name    string  `validate:"max_len=64"`
    Age     uint    `validate:"min=18"`
    Emails []string `validate:"min_items=1,item=[min_len=5]"`
}

//generates:
func (r User) Validate() error {
    if utf8.RuneCountInString(r.Name) > 64 {
        return fmt.Errorf("field Name is longer than 64 chars")
    }
    if r.Age < 18 {
        return fmt.Errorf("field Age is shorter than 18 chars")
    }
    if len(r.Emails) < 1 {
        return fmt.Errorf("array Emails has less items than 1 ")
    }
    for _, x := range r.Emails {
        _ = x
        if utf8.RuneCountInString(x) < 5 {
            return fmt.Errorf("field x is shorter than 5 chars")
        }
    }
    return nil
}
Some other examples:

How to generate?

genval mypkg

or you can use it as go:generate directive

//go:generate genval mypkg

Supported tags

  • String: min_len, max_len - min and max valid lenghth
  • Number: min, max - min and max valid value (can be float)
  • Array: min_items, max_items - min and max count of items in array
    item - scope tag, contains validation tags for each item
  • Pointer: nullable, not_null - it's clear
  • Interface: func - the same as for struct (func NameOfTheFunc(i interface{})error{..})
  • Struct: func - name of the method of this struct (func(s Struct) MethodName()error{..})
    or name of the func that will be used for validation (func nameOfTheFunc(s Struct)error{..})
    Methods should starts from '.'
    Can be used not once: func=.MethodName,func=nameOfTheFunc or even func=.MethodName;nameOfTheFunc
  • Map: min_items, max_items - min and max count of items in map
    key, value - scope tags, contains validation tags for key or value

Enum support

Go doesn`t support enums, but you can create some custom type and add few constants with required values.

type State int

const (
    StateOk    State = 200
    StateError State = 400
)

//generates:
func (r State) Validate() error {
    switch r {
    case StateOk:
    case StateError:
    default:
        return fmt.Errorf("invalid value for enum State: %v", r)
    }
    return nil
}

Some tips

  1. don`t use interface{} if you can
  2. commit generated code under source control
  3. read generated code if needed, do not afraid it

Custom validation

Additional validation

In some cases it`s required to add some custom validation. You can just add unexported validate method.

type User struct {
    Name  string `validate:"max_len=64"`
    Age   uint   `validate:"min=16"`
    Email string
}

func (u User) validate() error {
    if u.Age < 18 && u.Email == "" {
        return errors.New("email is required for people younger than 18")
    }

    return nil
}

// generates:
func (r User) Validate() error {
	if utf8.RuneCountInString(r.Name) > 64 {
		return fmt.Errorf("field Name is longer than 64 chars")
	}
	if r.Age < 16 {
		return fmt.Errorf("field Age is less than 16 ")
	}

	return r.validate() // custom validation call
}

Override validation

If you don`t want to use genval for some structs or use just custom validation then you can override exported Validate method. In this case genval will generate nothing for this struct.

About

Generates Validate() methods for structs by tags

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 99.9%
  • Makefile 0.1%