Skip to content

Instantly share code, notes, and snippets.

@mdwhatcott
Last active November 4, 2015 23:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdwhatcott/bc84abca4aaa5238e751 to your computer and use it in GitHub Desktop.
Save mdwhatcott/bc84abca4aaa5238e751 to your computer and use it in GitHub Desktop.
One way to validate struct fields that are strings, and that have a struct tag with a regex.
package web
import (
"bytes"
"reflect"
"regexp"
"fmt"
"errors"
"strings"
)
func Validate(s interface{}) error {
problems := &bytes.Buffer{}
value := reflect.ValueOf(s)
type_ := reflect.TypeOf(s)
for i := 0; i < type_.NumField(); i++ {
field := type_.Field(i)
if field.Type.Kind() != reflect.String {
continue
}
fullTag := string(field.Tag)
required := fullTag == "required" || strings.Contains(fullTag, " required") || strings.Contains(fullTag, "required ")
input := value.Field(i).String()
if required && len(input) == 0 {
fmt.Fprintf(problems, "Missing required field ('%s').\n", field.Name)
continue
}
tag := field.Tag.Get("validate")
if len(tag) == 0 {
continue
}
re, err := regexp.Compile(tag)
if err != nil {
return err
}
if !re.MatchString(input) {
fmt.Fprintf(problems, "Invalid field ('%s'): '%s'\n", field.Name, input)
}
}
if problems.Len() > 0 {
return errors.New(problems.String())
}
return nil
}
package web
import (
"testing"
"github.com/smartystreets/assertions"
"github.com/smartystreets/assertions/should"
)
type Input struct {
Field1 string `validate:"^Hello World$" required`
Field2 int
}
func TestValidationUsingStructTags(t *testing.T) {
assert := assertions.New(t)
good := Input{Field1:"Hello World"}
bad := Input{Field1:"Hello, Universe"}
missing := Input{Field1:""}
assert.So(Validate(good), should.BeNil)
assert.So(Validate(bad).Error(), should.ContainSubstring, "Invalid field ('Field1'): 'Hello, Universe'")
assert.So(Validate(missing).Error(), should.ContainSubstring, "Missing required field ('Field1').")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment