Advertisement

Go is an open source programming language developed at Google and designed to help build simple reliable software systems. The core strength of Go is its concurrency mechanisms which make it simpler to write software, to exploit multi-core architectures.

It's a compiled, strongly - statically typed, concurrent and garbage-collected language.

It's a very interesting, modern day language because of some of the choices that have been made during its design. For example, the Type System, although Go has methods and also an OO style of programming, there is no type hierarchy. The only way to achieve that is through interfaces.

How Go Differs From Others

One should read the language specification to get a better understanding of the design elements of the language. It is really concise and helps bring out some really interesting details. The way Go differs from other typical programming languages, is that it has features unlike other OO languages:

  • No Type Inheritance
  • No overloading of methods and operators
  • Built in concurrency primitives, which make it really stand out from the crowd. It shares memory by communicating and not the other way round.
  • A toolchain that uses a traditional model of compile and link to generate binaries without external dependencies.
  • Maps are built in.

Code Organization

The Go code is kept under workspaces. It's just a directory hierarchy, as follows:

  • src - contains Go source files as packages
  • pkg - contains package objects
  • bin - contains executables

The Go tool builds the source packages and installs the resulting binaries in bin and pkg directories.

A Simple Web Application Using Go

Let's build a static site and then go on to improve it so that it behaves much more dynamically, based on user input.

The Static Site

The code structure for the static site looks like so:

So, essentially you would want to create a structure similar to the above image or as is showed in the repository. This repo structure would itself reside under the workspace . Read about the Go Code Structure for more information.

Now what we want to do is serve an HTML file residing in the public directory.

The index.html contents are as follows:

<!DOCTYPE html>
 <html>
   <head>
     <title>Static site using Go</title>
     <link rel="stylesheet" type="text/css" href="stylesheets/gostatic.css">
   </head>


   &lt;body&gt;
     &lt;h1&gt;Developing Website using Go&lt;/h1&gt;
     &lt;p&gt;I am a static page, being served to you with the help of Go lang.&lt;/p&gt;
   &lt;/body&gt;
 </html>

And here's the Go program to serve files statically from the public folder:

package main

import (
  "net/http"
)

func main() {
  fs := http.FileServer(http.Dir("public"))
  http.ListenAndServe(":8080", fs)
}

Allow me to explain:

  • net/http - this package provides HTTP client and server implementations.
  • FileServer - this function returns a handler that serves HTTP requests with the contents of the file system.

That's it. Really simple and to the point. You can run the code using the following: go run gostatic.go.

A Better Solution

However, this solution does not clearly separate the routing and serving concerns and hence, a better solution would be along the lines of:

package main

import (
 "net/http"
 "log"
)

func main() {
  fs := http.FileServer(http.Dir("public"))
  http.Handle("/", fs)
  log.Println("Listening...")
  err := http.ListenAndServe(":8080", nil)
  if err != nil {
    log.Fatal("ListenAndServe: ", err)
 }
}

ListenAndServe starts an HTTP server on the given TCP address and then calls Serve with a handler. This handler is typically nil, so that the default router (in Go’s case the DefaultServerMux can take over).

Now in regards to DefaultServeMux - Let's take a short detour to understand how Go does HTTP processing. It does so with the help of two primary things.

  • ServerMuxes - (Router) Its a multiplexer - essentially a HTTP router, which compares incoming requests against the defined list and then calls the associated handler.
  • Handlers - These are responsible for 'handling' the request, like responding with the appropriate headers, body etc. Any object obeying the Handler interface can act as one.

Go ahead and run the sample web app as done earlier and you should see the output!

Dynamic Sites - Adding a Timestamp on Every Refresh

Next, let's write the application so that it prints the current time, implying that on every refresh you get a different output. The Go code would look like so:

package main


 import (
   "fmt"
   "net/http"
   "time"
 )


 func main() {
     http.HandleFunc("/", handler)
     log.Println("listening...")
     err := http.ListenAndServe(":8080", nil)
     if err != nil {
         panic(err)
     }
 }


 func handler(w http.ResponseWriter, r *http.Request) {
     fmt.Fprintf(w, "Hello. The time is : " + time.Now().Format(time.RFC850))
 }

Here we have imported fmt to work with some printing functions. The fmt implements formatted I/O functions along the lines of C's stdio library.

We have also made use of HandleFunc which registers the URL path with the handler function in the DefaultServeMux. The function handler is of the type http.HandlerFunc. It takes an http.ResponseWriter and http.Request as its arguments. People familiar with Java servlets would remember doing this!

To print out time, we import 'time' from the standard package and use it to respond back on the response writer object. By writing to http.ResponseWriter object we can send the response to the client.

http.Request is the structure that represents the HTTP request and hence has the entire request data. To access the URL path we do r.URL.path.

When you run this and then access localhost:8080 you should see the current time on every refresh.

Accepting User Input

Now let's write an application which accepts a username on the index page and then when the form is submitted, it greets the user on the next page.

Here's our Go code structure:

Lets first create an HTML file containing the form inside the public directory.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Go Greeter</title>
</head>
<body>
  <h1>Go Greeter</h1>
  <form action="/greet" method="post" accept-charset="utf-8">
    <input type="text" name="username" id="username" value="Enter username...">
    <input type="submit" value="Greet me!">
  </form>
</body>
</html>

This form, on submit, will redirect to /greet. Let's also write the contents of the greet.html file inside the public directory, which we would render when the request comes to /greet.

<!DOCTYPE html>
 <html>
  <head>
    <meta charset="utf-8">
    <title>Go Greeter</title>
  </head>
  <body>
    <pre>Hello {{.}}</pre>
  </body>
</html>

The Go code is as follows:

package main


import (
  "log"
  "net/http"
  "html/template"
)


func main() {
  http.HandleFunc("/", root)
  http.HandleFunc("/greet", greeter)
  log.Println("Listening...")
  err := http.ListenAndServe(":8080", nil)
  if err != nil {
    log.Fatal("ListenAndServe: ", err)
   }
}


func root(w http.ResponseWriter, r *http.Request) {
  t, _ := template.ParseFiles("public/index.html")
  t.Execute(w, nil)
}


func greeter(w http.ResponseWriter, r *http.Request) {
  username := r.FormValue("username")
  t, _ := template.ParseFiles("public/greeter.html")
  err := t.Execute(w, username)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
  }
}

We've used html/template to keep the HTML code in templates and then using them to render, on request.

There is a curious looking {{.}} in the greeter.html file. The html/template package assumes that plain text is always produced. It adds escaping wherever necessary to safely embed that plain string in correct context. When a data value is not plain text, we can make sure it is not escaped by specifying its type. So essentially, Hey, {{.}}! can be invoked by using tmpl.Execute(out, HTML('<i>Nishant</i>')) to produce Hey, <i>Nishant</i>!. Go ahead, try that!

Since the basic application is now working, we can finally deploy it to Heroku.

Deploying to Heroku

Once you have the heroku-toolbelt correctly setup and the repo managed via Git, we can deploy it along these lines.

The only change we would need to do in the code for deploying to Heroku, is change the line where we listen on a specific port.

Change:

 http.ListenAndServe(":8080",...) 

to:

http.ListenAndServe(":"+os.Getenv("PORT"),....

Heroku Setup

In order to deploy to Heroku, you will need a Heroku user account. You will also need a Heroku command-line client. Get it by installing the Heroku Toolbelt if not already.

Once installed, login using the Heroku account by saying heroku login, and then upload your SSH key. With these things in place, you should be ready to deploy to Heroku.

Deploying the Application

In order to deploy to Heroku, we need the app to be stored in Git.

git init .
git add -A .
git commit -m 'first heroku go app'

We will also need a Procfile to tell Heroku that the command it needs to run for the web process is our app.

echo 'web: gogreeter' > Procfile

Go package dependencies are managed on Heroku with the help of Godep packages.

Install Godep and save your dependencies using the following:

go get github.com/kr/godep
godep save

Add these new files to Git:

git add -A .
git commit -m 'godep'

Finally, create the Heroku application. It can be done like so:

heroku create -b https://github.com/kr/heroku-buildpack-go.git

This should create a Git remote in your repository by the name of heroku. You are ready to deploy now! Run the following:

git push heroku master

After the above command completes, your app should be up and running!

Go visit the URL by saying heroku open or by directly visiting the app URL that you see in the console.

That's it. You now have a Go application up and running on Heroku!

Summary

In this tutorial we learned how easy it is to develop a Go web application and also deploy it on Heroku. These days, web development is largely dependent on the frameworks that one uses. To explore some of these options, you should definitely check some of these projects.

Advertisement