Example of a database-backed service in Go
Go Shell
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
Godeps
bin
migrations
script
.gitignore
.travis.yml
FEATURES.md
LICENSE.md
Procfile
README.md
TODO.md
Vagrantfile
config.go
error.go
fernet.go
helpers_test.go
main.go
model.go
pg.go
pg_json.go
redis.go
scheduler.go
scheduler_test.go
validate.go
vm.sh
web.go
web_worker_test.go
worker.go

README.md

pgpin

pgpin is an open-source example app showing how to build a database-backed service in Go.

The example is a clone of Heroku Dataclips, basically a "pastebin for SQL queries".

In working through this example app we hope to learn:

  • How to build database-backed services in idiomatic Go, with an eye towards robustness and operability.

  • How developing such services in Go compares to other stacks, such as Ruby/Sinatra/Sequel.

Work on pgpin is ongoing. The current version of the app has some but not all of the user-facing features and robustness properties we eventually want. See FEATURES.md and TODO.md.

Developing

A Vagrant development environment is provided. Install a recent version of Vagrant and Virtualbox and run:

$ vagrant up
$ vagrant ssh

To start a development version of app:

$ cat migrations/* | psql $DATABASE_URL
$ godep go install
$ goreman start

An environment variable is provided to make testing with curl easy:

$ curl -i $PGPIN_URL/status

To apply code changes:

$ godep go install
$ goreman start

We suggest a git pre-commit hook to verify adherence to Go coding standards:

$ cat > .git/hooks/pre-commit <<EOF
#!/bin/bash

gofmt -d *.go 2>&1 | tee /tmp/pgpin-pre-commit
if [ \$(wc -l < /tmp/pgpin-pre-commit) -gt "0" ]; then
  exit 1
fi
go vet github.com/mmcgrana/pgpin || exit 1
errcheck -ignore 'fmt:a^' github.com/mmcgrana/pgpin || exit 1
EOF
$ chmod +x .git/hooks/pre-commit
$ go get github.com/kisielk/errcheck

Testing

To run tests:

$ cat migrations/* | psql $TEST_DATABASE_URL
$ godep go test

By default logs are silenced during tests. Turn them on with:

$ TEST_LOGS=true godep go test

Scripting

To write and run one-off scripts that use the pgpin app code:

$ cat > script/count_pins.go <<EOF
package main

import (
    "log"
    pgpin "../../pgpin"
)

func main() {
    pgpin.PgStart()
    count, _ := pgpin.PgCount("SELECT count(*) from pins")
    log.Printf("pins.count total=%d", count)
}
EOF

$ godep go run script/count_pins.go

Deployment

To an instance of pgpin to Heroku:

$ export DEPLOY=... (e.g. "production", or your username)
$ bin/deploy-setup
$ curl -i https://pgpin-$DEPLOY.herokuapp.com/status

To tear it down:

$ bin/deploy-teardown

License

See LICENSE.md.

References

Some other projects we've looked to in writing the pgpin example app:

We are interested in collecting other examples of non-trivial, open-source, database-backed (Postgres or otherwise) services written in Go. Please send suggestions to the author.