Skip to content

Instantly share code, notes, and snippets.

@mattreduce

mattreduce/go.md Secret

Created August 3, 2012 01:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattreduce/d2c1e1f7f0720de45536 to your computer and use it in GitHub Desktop.
Save mattreduce/d2c1e1f7f0720de45536 to your computer and use it in GitHub Desktop.
Go Buildpack Quickstart

This quickstart will get you going with Go on Heroku.

Prerequisites

Local Workstation Setup

We'll start by setting up your local workstation with the Heroku command-line client and the Git revision control system; and then logging into Heroku to upload your ssh public key. If you've used Heroku before and already have a working local setup, skip to the next section.

See the Heroku Toolbelt site for installation.

Once installed, you'll have access to the heroku command from your shell. Log in using the email address and password you used when creating your Heroku account:

$ heroku login
Enter your Heroku credentials.
Email: kr@example.com
Password: 
Could not find an existing public key.
Would you like to generate one? [Yn] 
Generating new SSH public key.
Uploading ssh public key /Users/kr/.ssh/id_rsa.pub

Press enter at the prompt to upload your existing ssh key or create a new one, used for pushing code later on.

Installing Go

It's easiest to install Go from one of the official Go packages provided by the Go team.

See the Go getting started page for full installation instructions and How to Write Go Code to learn how best to set up your local environment, including what values to use for environment variables and which directories to use. Here's a summary.

Make a directory to hold all your Go source:

$ mkdir -p $HOME/gocode/src

The go tools use env var GOPATH to find source code to build on your system, so put the following in your $HOME/.profile:

GOPATH=$HOME/gocode export GOPATH

And run

$ . $HOME/.profile

to pick up this change in your current shell.

Write Your Application

Now it’s time to create a simple “hello, world” application.

First, make a directory to hold your new Heroku app, and initialize an empty git repository there:

$ mkdir -p $GOPATH/src/example.com/server
$ cd $GOPATH/src/example.com/server
$ git init

Here’s the actual application code:

app.go

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    http.HandleFunc("/", hello)
    err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

func hello(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(w, "hello, world!")
}

Build your App and its Dependencies

The Go buildpack recognizes Go apps by the existence of a .go source file anywhere in the repository.

Your app and its dependencies are built all together by the go command-line tool.

You can build your app using go get:

$ go get

Declare Process Types With Foreman and Procfile

To run your web process, you need to declare what command to use. In this case, we simply need to execute our Go program. We’ll use Procfile to declare how our web process type is run.

Foreman is documented in the foreman man page and Heroku's Procfile support in a separate devcenter article.

Here's a Procfile for the sample app we've been working on:

web: server

Now that you have a Procfile, you can start your application with Foreman:

$ foreman start
13:58:29     web.1  | started with pid 5997

Your app will come up on port 5000. Test that it's working with curl or a web browser, then Ctrl-C to exit.

Set a Hint for the Go Buildpack

The go tool uses the directory name of your project to name executables and determine package import paths, but the Go buildpack doesn't have direct access to this information, so you have to tell it. Cretate a file called .godir, in your project root, containing the path from $GOPATH/src to your project root, in this case example.com/server:

$ echo example.com/server >.godir

Store Your App in Git

We now have the three pieces of our app: application source in app.go, process types in Procfile, and the path to the project. Let's put it into Git:

$ git add .
$ git commit -m init

Deploy to Heroku

Create the app:

$ heroku create
Creating pure-sunrise-3607... done, stack is cedar
http://pure-sunrise-3607.herokuapp.com/ | git@heroku.com:pure-sunrise-3607.git
Git remote heroku added

and tell it to use the Go Buildpack:

$ heroku config:add BUILDPACK_URL=git://github.com/kr/heroku-buildpack-go.git
Adding config vars:
  BUILDPACK_URL => git://github.com...dpack-go.git
Restarting app... done, v1.

Deploy your code:

$ git push heroku master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 687 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Fetching custom buildpack... done
-----> Go app detected
-----> Using Go go1
-----> Running go get and go install
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 1.0MB
-----> Launching... done, v1
       http://pure-sunrise-3607.herokuapp.com deployed to Heroku

To git@heroku.com:pure-sunrise-3607.git
 * [new branch]      master -> master    

Now, let's check the state of the app's processes:

$ heroku ps
UPID      Process       State               Command
--------  ------------  ------------------  ------------------------------
19237303  web.1         up for 11m          server

The web process is up. Review the logs for more information:

$ heroku logs
2012-08-03T01:17:15+00:00 heroku[api]: Deploy db538ce by kr@example.com
2012-08-03T01:17:15+00:00 heroku[api]: Release v4 created by kr@example.com
2012-08-03T01:17:16+00:00 heroku[slugc]: Slug compilation finished
2012-08-03T01:17:19+00:00 heroku[web.1]: Starting process with command `server`
2012-08-03T01:17:20+00:00 heroku[web.1]: State changed from starting to up

Looks good. We can now visit the app with heroku open.

Running a Worker

The Procfile format lets you run any number of different process types. For example, let's say you wanted a worker process to complement your web process. Just add another directory containing the source code for your worker command, work/work.go, and build as usual with the go tool:

$ go get ./work

Procfile

web: server
worker: work

(Running more than one dyno for an extended period may incur charges to your account. Read more about dyno-hour costs.)

Push this change to Heroku, then launch a worker:

$ heroku scale worker=1
Scaling worker processes... done, now running 1

Check heroku ps to see that your worker comes up, and heroku logs to see your worker doing its work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment