4 ms·
This article turns into the creation of a small web app, so while not exactly relevant, I'll ask here: are there any good form validation libraries for Go? I e
by aaron-lebo 12y ago
This article turns into the creation of a small web app, so while not exactly relevant, I'll ask here: are there any good form validation libraries for Go?
I ended up using this approach:
http://www.alexedwards.net/blog/form-validation-and-processing http://www.alexedwards.net/blog/form-validation-and-processi...
This is straightforward but also manual and low-level.
In comparison is Python's formencode library which is declarative and high-level:
class Registration(formencode.Schema):
first_name = validators.ByteString(not_empty=True)
last_name = validators.ByteString(not_empty=True)
email = validators.Email(resolve_domain=True)
username = formencode.All(validators.PlainText(),UniqueUsername())
password = SecurePassword()
password_confirm = validators.ByteString()
chained_validators = [validators.FieldsMatch('password', 'password_confirm')]
I thought about how you could design a library like this in Go, but couldn't think of a way that did not end up using reflection or plain maps, which defeats the purpose of using static typing.
Is this lack of validation libraries due to the lack of people writing web apps with the language or is it a problem of expressiveness with the language itself?
I ran into this issue several times when trying to write a web app in Go. A lot of the basic infrastructure is there, but the niceties are missing. The template language, for example, is great but lacks something as basic as inheritance without kludges. There are other templating languages, but they don't feel quite there. Got the same feel from the ORMs. Hats off to those who are doing work in it in spite of this, but it seems there's a way to go before the language is really usable for web apps.
- murz 12y ago> are there any good form validation libraries for Go? Here are a couple: http://www.gorillatoolkit.org/pkg/schema http://www.gorillatoolkit.org/pkg/schema http://godoc.org/github.com/mccoyst/validate http://godoc.org/github.com/mccoyst/validate There are also some bigger web framework projects that include validation, Revel is one: http://revel.github.io/manual/validation.html http://revel.github.io/manual/validation.html
- aaron-lebo 12y agoschema is not a validation library, it just turns HTTP forms into Go structs. Validate uses tags or maps (not a huge issue, granted). The Revel one does look nice, though. Thanks.
- aaronblohowiak 12y ago>couldn't think of a way that did not end up using reflection The builtin decoders (eg, json) use reflection. You don't lose any of the benefits of static typing as you are still decoding into your statically-typed object. I would separate form parsing from object validation. Use something like this: https://github.com/ajg/form https://github.com/ajg/form to populate statically-typed go structs from form data, and then validate your objects.
- aaron-lebo 12y agoThere is a speed hit to reflection, though, right? Also, you do lose the benefit of static typing, for example, the following typo isn't picked up at compile time: type User struct { Name string `form:"nam"` } Tags are rather ugly and don't scale to many options well. What happens when your ORM, form validation library, xml library, and json libraries each need a separate tag? That's a slight exaggeration but you could see how the apparent simplicity in the form example can quickly become anything but. Heavy use of tags (and reflection) just makes me feel like you have to work around the language too much and I question whether you may as well just use Python, hence my original question. I've done minimal work with Go, though, so perhaps I'm misinformed.
- placeybordeaux 12y agoThere is a speed hit to reflection. As for the tag issue: writing your own marshaler isn't actually a huge problem. I have been meaning to write my own json marshaler for a while. I personally find the solution much more paletable than many other ways of marshaling in and out of json.
- dsymonds 12y agoThere's a significant speed hit to reflection, but it's going to get lost in the noise if you're making HTTP requests.
- cakoose 12y agoYou're example is not a static typing issue. It's a feature of the library that the struct field doesn't have to have the same name as the form field. I think the issue is more of a DRY thing, which could maybe be fixed with something like: type User struct { FirstName string `form:lowercase_hyphenated` LastName string `form:lowercase_hyphenated` } This hypothetical syntax would instruct the library to look for the form fields "first-name" and "last-name".
- elithrar 12y agoI've attacked this from a few angles myself—previously using reflection and struct tags - `min:"2", max:"50"` - but found it fairly inelegant (although practical). I wrote some good tests around it, that's for sure. Now I'm a fan of https://github.com/katco-/vala https://github.com/katco-/vala which has a nice API for doing this for you. I've ripped out one of the examples from the README (which I think illustrates it well), but you could also wrap this in a method that you call on the instance of the struct you get back from (i.e.) gorilla/schema: func ClearValidation(a, b, c MyType) (err error) { err = BeginValidation().Validate( IsNotNil(a, "a"), IsNotNil(b, "b"), IsNotNil(c, "c"), ).CheckAndPanic().Validate( // Panic will occur here if a, b, or c are nil. HasLen(a.Items, 50, "a.Items"), GreaterThan(b.UserCount, 0, "b.UserCount"), Equals(c.Name, "Vala", "c.name"), Not(Equals(c.FriendlyName, "Foo", "c.FriendlyName")), ).Check() if err != nil { return err } // ... } Note that for any reasonable amount of validation w/ structs (i.e. not nil, ranging over it automatically, etc) you will need reflection. There are no ifs or buts about that. But the whole 'reflection is slow' mantra is premature optimisation: if you need reflection, you need it. Your template rendering uses reflection, your database connection introduces latency, etc - all of that dwarfs any cost associated with validating a struct or two.
- aaron-lebo 12y agoThanks for your response. It is good to hear from someone who has wrestled with the issue.