Form Validation and Processing in Go

1st November 2013

In this post I'm going to run through a start-to-finish tutorial for building a online contact form in Go. I'll be trying to explain the different steps in detail, as well as outlining a sensible pattern for processing that can be extended to other forms.

Let's begin the example by creating a new directory for the application, along with a main.go file for our code and a couple of vanilla HTML templates:

Our contact form will issue a POST request to /, which will be the same URL path that we use for presenting the form. This means that we'll need to route requests for the same URL to different handlers based on the HTTP method.

There are a few ways of achieving this, but we'll use Pat – a third-party routing library which I've talked about before. You'll need to install it if you're following along:

This is fairly straightforward stuff so far. The only real point of note is that we've put the template handling into a render function to cut down on boilerplate code.

If you run the application:

$ go run main.go
Listening...

And visit localhost:3000 in your browser you should see the contact form, although it doesn't do anything yet.

Now for the interesting part. Let's add a couple of validation rules to our contact form, display the errors if there are any, and make sure that the form values get presented back if there's an error so the user doesn't need to retype them.

One approach to setting this up is to add the code inline in our send handler, but personally I find it cleaner and neater to break out the logic into a separate message.go file:

We've started by defining a new Message type, consisting of the Email and Content values (which will hold the data from the submitted form), along with an Errors map to hold any validation error messages.

We then created a Validate method that acts on a given Message, which summarily checks the format of the email address and makes sure that the content isn't blank. In the event of any errors we add them to the Errors map, and finally return a true or false value to indicate whether validation passed successful or not.

This approach means that we can keep the code in our send handler fantastically light. All we need it to do is retrieve the form values from the POST request, create a new Message object with them, and call Validate(). If the validation fails we'll then want to reshow the contact form, passing back the relevant Message object.

As a side note, in this example above we're using the FormValue method on the request to access the POST data. We could also access the data directly via r.Form, but there is a gotcha to point out – by default r.Form will be empty until it is filled by calling ParseForm on the request. Once that's done, we can access it in the same way as any url.Values type. For example:

Still, our contact form is pretty useless unless we actually do something with it. Let's add a Deliver method which sends the contact form message to a particular email address. In the code below I'm using Gmail, but the same thing should work with any other SMTP server.

Additional Tools

If mapping form data to objects is something that you're doing a lot of, you may find Gorilla Schema's automatic decoder useful. If we were using it for our contact form example, the code would look a bit like this:

Additionally, Goforms appears to be a promising idea, with a fairly slick Django-like approach to dealing with forms. However, the existing validation options are fairly limited and the library doesn't seem to be under active development at the moment. It's still worth a look though, especially if you're thinking of rolling something a bit more generic for your form handling.

If you found this post useful you might like the book I'm writing: Building real-world web applications in Go.