Go: Building Web Applications with Beego

By Matthew Setter

Building Web Applications With Beego

Developing a web application with Beego - Part 1


Are you a web application developer coming to Go from a dynamic language as PHP, Python or Ruby, and wondering how to develop web-based applications using it? Are you wondering how to develop in a manner analogous to your existing frameworks, where you can leverage your existing knowledge?

If so, then you’ve likely done some searching, whether on Google, StackOverflow or other sites, in search of a framework to help you out; and you may have seen that there are a number of options available, including Beego, Martini and Gorilla; in addition to the net/http package.

Of these four, the one that I’ve been experimenting quite a lot with is Beego. I’ve found that it’s quite feature rich, yet not overly complicated, so I’ve been able to get up to speed with it relatively quickly.

Beego is not your average web development toolkit. As well as providing a lot of functionality, it builds on a large number of existing Go packages, which allows it to provide:

  • A full ORM
  • Caching
  • Session support
  • Internationalization (i18n)
  • Live monitoring and reloading
  • Deployment support.

But whilst there are a number of similarities between Beego and the frameworks from the previously mentioned dynamic languages, there are enough differences between them to require some time to be invested before becoming truly productive and proficient.

Furthermore, whilst the Beego documentation is quite comprehensive, I feel that it suffers a bit by missing points here and there, so I’ve written this 2-part series to help overcome that and help you learn the basics of Beego.

In this series you’ll see just what an excellent framework it is and how much it takes care of for us as developers. Specifically, here in part 1 we’ll cover:

  • Installing Beego and the command line tool Bee
  • Creating a project
  • Actions
  • Views / Templates
  • Routing
  • Request Parameters

If you want to read through the completed code for this series, it’s available on Github. Feel free to browse it online or clone it and experiment with it. Let’s Go!

Before we get started, make sure that your GO environment is set up. If it’s not, or you’re not sure what I mean, check out Getting Started with Go or this post from Bill Kennedy, then come back and let’s continue.

1. Installing Beego

Ok, let’s start off by installing Beego. Like a number of frameworks and toolkits, Beego has in-built scaffolding support, via the command line tool bee. Bee can:

  • Create new applications
  • Run an application
  • Test the application
  • Create routes and more

Bee isn’t the only way to run Beego apps, but it’s the one I’ll be covering in this 2-part series. To install it, run go get

2. Creating The Core Project

Once installed, from your $GOPATH directory, run the following command, which will scaffold the application, called sitepointgoapp:

bee new sitepointgoapp

This displays output similar to the following:

[INFO] Creating application…
14-05-14 06:02:59 [SUCC] New application successfully created!

You’ll now see the following directory structure has been created:

    ├── conf
   └── app.conf
├── controllers
   └── default.go
├── main.go
├── models
├── routers
   └── router.go
├── static
   ├── css
   ├── img
   └── js
├── tests
   └── default_test.go
└── views
    └── index.tpl

Looking at the files, we have:

  • Our bootstrap file main.go
  • The core configuration file conf/app.conf
  • A default controller controllers/default.go
  • A default set of tests in tests/default_test.go
  • A default view template in views/index.tpl

Right, the basic app is ready to go so let’s get it up and running. From the project directory, $GOPATH/src/sitepointgoapp/, run the following command:

bee run

This loads our new application. As a side benefit, bee also monitors the source files for modifications. If changes are detected, bee will reload the application automatically. After running the command above, you should see output similar to that below.

14-05-05 11:34:17 [INFO] Start building...
14-05-05 11:34:20 [SUCC] Build was successful
14-05-05 11:34:20 [INFO] Restarting sitepointgoapp ...
14-05-05 11:34:20 [INFO] ./sitepointgoapp is running...
2014/05/05 11:34:20 [I] Running on :8080

You can see that the application’s ready to run on port 8080. Loading up http://localhost:8080/ in the browser shows the following output:

Beego App Home Page

It’s nothing too flashy, but works. So let’s get our hands dirty and extend the default controller, adding in a new action, along with some custom routes.

3. Adding a New Action

Opening up controllers/default.go, you’ll see a pretty bare bones controller. This is because the display logic is all contained in the view template. Let’s change that around a bit and see how to add view template variables and specify a template file. In default.go, add the following method:

func (main *MainController) HelloSitepoint() {
    main.Data["Website"] = "My Website"
    main.Data["Email"] = ""
    main.Data["EmailName"] = "Your Name"
    main.TplNames = "default/hello-sitepoint.tpl"

Let’s step through what that means. What we’ve done is to add a new method (or action) Get onto the current controller, by specifying main *MainController as the receiver of the method.

We’ve then initialised three template variables, Website, Email and EmailName, by storing them in a field in the Controller, called Data, which is a map representing template variables and values.

Following that, I’ve specified the template file name, by setting this.TplNames to default/hello-sitepoint.tpl. In case you’re wondering, by default Beego will look in the views directory for the file specified.

So when this route is executed, Beego will fetch views/default/hello-sitepoint.tpl and render it.


Right, let’s create the accompanying view. Under views, create a new directory default and in there, create a new file hello-sitepoint.tpl, inserting the code below:

<header class="hero-unit">
    <div class="container">
        <div class="row">
            <div class="hero-text">
                <h1>Welcome to the Sitepoint / Beego App!</h1>
                <h2>This is My Test Version</h2>
                <p>{{.Website}} {{.Email}} {{.EmailName}}</p>

If this is your first time working with templates in Go, be aware that Beego’s template layer extends Go’s html/template package. For some good examples of using variables in templates, check out this example from the text/template package.

Like most Go packages, html/template is quite extensive, so I’ll stick just to the relevant features. All template variables are available in a global context, able to be accessed using the dot operator, embedded using the {{}} syntax.

So to access the three template variables we set in the controller action previously, we refer to them as {{.Website}}, {{.Email}}, and {{.EmailName}}.


Ok, we have a new action and an accompanying view. But we can’t yet execute the route. If we tried to access anything other than the default action, we’d see the default 404 error page, as in the screenshot below.

Beego 404 Page

So, we need to add a route to it. In routers/router.go update the init method to look as follows:

func init() {
    beego.Router("/", &controllers.MainController{})
    beego.Router("/hello-world", &controllers.MainController{}, "get:HelloSitepoint")

Focusing on the last line, what this does is call the HelloSitepoint action on the MainController when we attempt to dispatch to /hello-world. Save that and wait a short moment for the recompile to complete, then open http://localhost:8080/hello-world in your browser. All being well, it will look like the page below:

Beego Hello World Route

Request Parameters

Now what we’ve done so far is fine for simple actions. But in a real world application, we’ll interact with the request, inspecting the query string or POST data and then reacting accordingly. So how do we access that information with Beego?

Let’s start by retrieving data from the query string. Another of the pre-defined values in Beego is the Context Module which contains the Input value, which in turn encapsulates a request.

It provides us with access to such things as:

  • method
  • protocol
  • user agent
  • query (Get and Post data)
  • session information and more

Let’s make this a bit more interesting by updating the route to require an id value to be set, which we can then inspect and print out in the action. In router.go, change the /get route to the following:

beego.Router("/hello-world/:id([0-9]+)", &controllers.MainController{}, "get:HelloSitepoint")

Now, we need to supply a GET value which can only be a number, because of the regex we’ve supplied to the route, ([0-9]+). Save that and try and load /hello-world again without id. Do you see an error?

Now dispatch to /hello-world/213 and it should complete successfully. Now that it does, let’s get a hold of the information. In the Get method, add in the following, above this.TplNames:

this.Data["Id"] = this.Ctx.Input.Param(":id")

Then in hello-world.tpl add the following next to the existing template variables: {{.Id}}. Reloading the page will now display 213 next to Email Name.

Restricting Actions By Method Type

Ok, we’re just about done for today, but I want to cover one last thing before we go. Often times, you want to restrict access to an action to one or more specific methods. For example, you may only want to access a delete route, with a POST request; you may only want to display search results with a GET request.

Beego makes it easy to access an action via all types, or restrict it to one or a few. In router.go again, change the /hello-world route further to the following:

beego.Router("/hello-world/:id([0-9]+)", &controllers.MainController{}, "get,post:Get")

What this has done is allow dispatches to be made the /hello-world/ as either GET or POST requests. Try curl’ing it either a PUT or DELETE, using the following examples, and see what you get.

# PUT request
curl -X PUT http://localhost:8080/hello-world/213

# DELETE request
curl -X DELETE http://localhost:8080/hello-world/213

Wrapping Up

I hope you’ve enjoyed this introduction to the Beego web application framework. In part 2, we’ll be integrating a database (SQLite3), looking a Models, Forms and Validation.

At the end of part 2, we’ll have a nicely rounded out application, covering the majority of features you’d expect to use day to day.

Whilst Beego and Go are different from the dynamic languages you may be used to using, with a little bit of time and effort, it’s pretty simple to harness the power that they provide.

Don’t forget, the code for this series is available on Github. Feel free to browse it on online or clone it and experiment with it.

What did you think? Is this enough to get you using Go, if you aren’t already? Share your thoughts in the comments.

  • Hans Keeler

    You reference a `get.tpl` template and `/get` route in this post a few times. Should those be `hello-sitepoint.tpl` and `/hello-world`?

    • Hi Hans thanks for the comment. The route’s fine, but you’re right about the template. I’ll get that updated soon.

      • Marcel

        Hi Matthew,

        I could follow your post, but I got lost in the “Request Parameters” section.
        You write: In the Get method, add in the following, above this.TplNames:

        In which file should I write: this.Data[“Id”] = this.Ctx.Input.Param(“:id”) ?

        Thanks a lot for your help!

  • astaxie

    wow, it’s really a good tutorial. Thanks Matthew.

  • Do this mean, It is not possible to install or deploy it on a shared hosting?

    • emadera52

      I’m using Go (with Beego) on a Webfaction shared server. Search for “go webfaction Kallhoff” to find an article explaining the setup.

      The short version is 1) set up the application as “Custom” after which Webfaction provides a port number. 2) update Beego’s default “conf” file to reflect the correct port.

  • carlos munoz

    Regards Hello., I want to thank you for writing this example has helped me a lot to understand more beego.

    Following your example, I had trouble with the form, to give click, the button “submit” the form is not refreshed me and keeps the data I have finished entering.

  • davidemo89

    Hi, how is possible to unescape strings? I have a query from the database that read an array of articles in a struct

    type Blog struct {
    Id int
    Title string
    Date int
    Author string
    ImgHome string
    TestoCorto string
    TestoLungo string


    In the database there are some html strings for the article and when I output all articles

    this.Data[“blogs”] = models.GetAllBlogs()

    Every html get escaped :-( I have to unescape the arrays. How can I do it?

    Thank you!

  • Michael,

    Thanks for replying with the question. You add that to default.go. Sorry that I wasn’t clearer about that in the article.

  • Bob Follek

    Good tutorial. Thanks. I think the line

    this.Data[“Id”] = this.Ctx.Input.Param(“:id”)

    should be

    main.Data[“Id”] = main.Ctx.Input.Param(“:id”)

    • Thanks Bob. I’ll go back over the code and check that out.

  • Hung Son Pham

    tks for the excellent tutorial, is this here a small typo:
    beego.Router(“/hello-world/:id([0-9]+)”, &controllers.MainController{}, “get,post:Get”)

    it should be (…. , “get,post:HelloSitePoint”) right ?

    • Sorry to not get back to you for so long. I’ll check that out and get it corrected.

  • murat

    Thank you for this great and simple document.

  • satrio arif wicaksono

    I don’t know why I test on windows method POST are not work with curl -X PUT but work without -X option.

Get the latest in Front-end, once a week, for free.