Go + Heroku : Hello World

What is Go

Go is an open source programming language with built-in concurrency primitives, type safety, fast compile time, automatic memory management and a comprehensive standard library. It’s fun to write and a great fit for web and other network services.

Installing Go

Install Go by following the installation instructions on the Go website for your specific OS.

$ go version
go version go1.4.2 darwin/amd64

Go Workspace

Go code is organized into a workspace rooted at $GOPATH. A workspace contains the source code for multiple go packages ($GOPATH/src/…) as well as compiled binaries ($GOPATH/bin) and intermediary compiled objects ($GOPATH/pkg/…). The go tooling expects your code to be arranged into one or more workspaces.

$ mkdir -p $HOME/go
$ export GOPATH=$HOME/go
$ export PATH=$GOPATH/bin:$PATH

Hello World Web Application

Start by creating the directory inside of $GOPATH that will hold the application’s source code:

mkdir -p $GOPATH/src/helloworld
package mainimport (
"log"
"fmt"
"net/http"
"os"
)
func determineListenAddress() (string, error) {
port := os.Getenv("PORT")
if port == "" {
return "", fmt.Errorf("$PORT not set")
}
return ":" + port, nil
}
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World")
}
func main() {
addr, err := determineListenAddress()
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/", hello)
log.Printf("Listening on %s...\n", addr)
if err := http.ListenAndServe(addr, nil); err != nil {
panic(err)
}
}
  1. main is the entry point into the application. It first tries to determine which address to listen on and if it can’t exits with an error. Otherwise hello is registered to handle all requests and listens on the address. If there is any problem listening on the address it panics, otherwise it starts servicing http requests.
  2. hello is the http.Handler that ‘says’ “Hello World”.
  3. determineListenAddress figures out what address to listen on for traffic. It uses the $PORT environment variable only to determine this. If $PORT isn’t set an error is returned instead.
$ go install ./...
$ PORT=5000 $GOPATH/bin/helloworld
Listening on 5000...
$ curl -i http://localhost:5000/
HTTP/1.1 200 OK
Date: Wed, 15 Apr 2015 06:32:33 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8
Hello World

Deploying To Heroku

The application is running locally, so let’s deploy it to Heroku.

Heroku Prerequisites

  1. Sign up for a Heroku account.
  2. Install the Heroku Toolbelt.
  3. Login with heroku login.

Preparing the application

Git is installed as part of the Heroku Toolbelt. We’ll use it to track and push the source code to Heroku.

$ git init
$ git add -A .
$ git commit -m “Hello World”
$ echo “web: helloworld” > Procfile
$ git add Procfile
$ git commit -m Procfile

Godep

The supported way to manage dependencies for Go applications on Heroku is via Godep. Install godep via:

$ go get -u github.com/tools/godep
$ godep save -r ./...
$ git add -A Godeps
$ git commit -m Godeps
$ cat Godeps/Godeps.json
{
“ImportPath”: “helloworld”,
“GoVersion”: “go1.4.2”,
“Packages”: [
“./…”
],
“Deps”: []
}

Heroku Deploy

Create a new Heroku app using the Go Buildpack:

$ heroku create -b https://github.com/heroku/heroku-buildpack-go.git
Creating sheltered-peak-9514... done, stack is cedar-14
Buildpack set. Next release on sheltered-peak-9514 will use https://github.com/heroku/heroku-buildpack-go.git.
https://sheltered-peak-9514.herokuapp.com/ | https://git.heroku.com/sheltered-peak-9514.git
Git remote heroku added
$ git push heroku master
Counting objects: 13, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (13/13), 1.37 KiB | 0 bytes/s, done.
Total 13 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: — — -> Fetching custom git buildpack… done
remote: — — -> Go app detected
remote: — — -> Installing go1.4.2... done
remote: — — -> Running: godep go install -tags heroku ./...
remote: — — -> Discovering process types
remote: Procfile declares types -> web
remote:
remote: — — -> Compressing... done, 1.6MB
remote: — — -> Launching... done, v3
remote: https://sheltered-peak-9514.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/sheltered-peak-9514.git
* [new branch] master -> master
$ heroku open
$ heroku ps
=== web (1X): `helloworld`
web.1: up 2015/04/14 23:55:51 (~ 6m ago)
$ heroku logs --tail
...
2015–04–15T06:59:39.396139+00:00 heroku[router]: at=info method=GET path=”/” host=sheltered-peak-9514.herokuapp.com request_id=f5a7d634-dbf0–42c2-a278-e1dc37c98178 fwd=”76.115.27.201" dyno=web.1 connect=0ms service=1ms status=200 bytes=148
...

Thanks

Thanks to Michelle Peot, Andrew Gwozdziewycz, Cyril David & Mark McGranaghan for reviewing and making suggestions.

--

--

I am too many things, yet not enough.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
freeformz

freeformz

I am too many things, yet not enough.