Blog

Go Buffalo – Rapid Web Development

27 Nov, 2018
Xebia Background Header Wave

When you want to create a rest service or web application in Go, you have to do a lot of work around project setup, application architecture, directory structures, and more. What if there was a web development platform that already has everything from front-end (JavaScript, CSS) to back-end (database, routing), designed to make the life of a Go web developer easier. Well, there is, it is called Buffalo. Lets take a look!

Buffalo

Buffalo is a web application development environment for Go, inspired by Ruby on Rails, the Play Framework, Django and other rapid application web frameworks. Buffalo makes use of the Gorilla toolkit, a web toolkit for Go.

Install

Buffalo can be installed by typing:

# from source with sqlite3 support
go get -u -v -tags sqlite github.com/gobuffalo/buffalo/buffalo

# from source *without* sqlite3 support
go get -u -v github.com/gobuffalo/buffalo-plugins

# using homebrew
$ brew install gobuffalo/tap/buffalo

After installation you should have the buffalo cli installed:

$ buffalo version
INFO[0000] Buffalo version is: v0.13.7

A REST API

Buffalo can also create simple REST APIs. Buffalo v0.13.7 does not support modules, so you have to create a directory in $GOPATH eg. $GOPATH/src/github.com/binxio/blog-go-buffalo and type the following

$ buffalo new go_blog_buffalo --api --skip-pop
$ cd go_blog_buffalo
$ buffalo dev
buffalo: 2018/11/27 19:16:41 === Rebuild on: :start: ===
buffalo: 2018/11/27 19:16:41 === Running: go build -v -i -tags development -o tmp/go-buffalo-build  (PID: 17379) ===
buffalo: 2018/11/27 19:16:42 === Building Completed (PID: 17379) (Time: 1.322165735s) ===
buffalo: 2018/11/27 19:16:42 === Running: tmp/go-buffalo-build (PID: 17397) ===
INFO[2018-11-27T19:16:45+01:00] Starting application at 127.0.0.1:3000
INFO[2018-11-27T19:16:45+01:00] Starting Simple Background Worker

The service is available at port ‘3000’:

$ http :3000
HTTP/1.1 200 OK
Content-Length: 34
Content-Type: application/json
Date: Tue, 27 Nov 2018 18:17:36 GMT
Vary: Origin

{
    "message": "Welcome to Buffalo!"
}

Generator

Buffalo comes with a generator that can generate Actions. Lets start a second terminal, navigate to $GOPATH/src/github.com/binxio/blog-go-buffalo and type:

$ buffalo g a cats List --skip-template

The generator has created a cats.go file with the CatsList action.
Change the following lines in app.go:

// change this line
app.GET("/cats/List", CatsList)

// to this line
app.GET("/cats", CatsList)

Notice that Buffalo automatically compiles and reloads the server to reflect the changes to the application.
Lets implement the CatsList handler in cats.go:

package actions

import "github.com/gobuffalo/buffalo"

type Cat struct {
    Name string `json:"name"`
    Age int `json:"age"`
}

var cats = []Cat {
    Cat { Name: "Elsa", Age: 16 },
    Cat { Name: "Tijger", Age: 12 },
}

// CatsList default implementation.
func CatsList(c buffalo.Context) error {
    return c.Render(200, r.JSON(cats))
}

Call the endpoint:

$ http :3000/cats
HTTP/1.1 200 OK
Content-Length: 54
Content-Type: application/json
Date: Tue, 27 Nov 2018 18:42:38 GMT
Vary: Origin

[
    {
        "age": 16,
        "name": "Elsa"
    },
    {
        "age": 12,
        "name": "Tijger"
    }
]

Lets add a new route with the command:

$ buffalo g a cats GetById --skip-template

Change the following lines in app.go:

// change this line
app.GET("/cats/GetById", CatsGetByID)

// to this line
app.GET("/cats/{id:[0-9]+}", CatsGetByID)

Add the following implementation to cats.go:

package actions

import (
    "github.com/gobuffalo/buffalo"
    "github.com/gorilla/mux"
    "net/http"
    "strconv"
)

type Cat struct {
    ID int `json:"id"`
    Name string `json:"name"`
    Age  int    `json:"age"`
}

var cats = []Cat{
    Cat{ID: 1, Name: "Elsa", Age: 16},
    Cat{ID: 2, Name: "Tijger", Age: 12},
}

func CatsList(c buffalo.Context) error {
    return c.Render(http.StatusOK, r.JSON(cats))
}

func CatsGetByID(c buffalo.Context) error {
    params := mux.Vars(c.Request())
    id, _ := strconv.Atoi(params["id"])
    for _, cat := range cats {
        if cat.ID == id {
            return c.Render(http.StatusOK, r.JSON(cat))
        }
    }
    return c.Render(http.StatusNotFound, nil)
}

And call the endpoint:

$ http :3000/cats/1
HTTP/1.1 200 OK
Content-Length: 32
Content-Type: application/json
Date: Tue, 27 Nov 2018 18:51:09 GMT
Vary: Origin

{
    "age": 16,
    "id": 1,
    "name": "Elsa"
}

Conclusion

Buffalo makes it really easy to create rest services. Buffalo creates a project skeleton, generates actions and templates, runs the server and provides hot reload on code change. We have created two actions, one for cats and one to get a cat by id. Buffalo makes use of the Gorilla toolkit what makes it easy for us to extend the REST service with functionality. I will definitely use Buffalo for a next project.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts