Deploying a Golang web apps to Heroku is quite easy.
Heroku configuration
Heroku configurations are fetched from the OS environment variables.
So to fetch the webapp port, you will need to call os.Getenv("PORT")
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package main
import (
"net/http"
"os"
"log"
"fmt"
)
func main() {
port := GetPort()
log.Println("[-] Listening on...", port)
http.HandleFunc("/", func (res http.ResponseWriter, req *http.Request) {
fmt.Fprintln(res, "hello, world")
})
err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
if err != nil {
panic(err)
}
}
func GetPort() string {
port := os.Getenv("PORT")
if port == "" {
port = "4747"
log.Println("[-] No PORT environment variable detected. Setting to ", port)
}
return ":" + port
}
|
That’s everything you need to do in your Golang webapp.
Now, you will need to tell Heroku to add the following buildpack to your webapps:
1
2
|
cd /path/to/golang/app
heroku create example -b https://github.com/kr/heroku-buildpack-go.git
|
Before pushing to Heroku, you will need to save your app dependencies.
Heroku support Godep for dependency management.
First install Godep:
1
|
go get -u github.com/tools/godep
|
Save your dependencies:
1
2
3
|
godep save
git add -A
git commit -m "Add Godep"
|
Now, you are good to go!
Adding a Database to your Web app
Heroku has made the life of developper easier. To add a new database to your webapp, it’s really easy.
For example, I needed to add a Postgresql. I just needed to execute one command line and the configuration is fetched from the environment variables:
1
|
heroku addons:add heroku-postgresql:dev
|
More information on Heroku’s documentation.
Now to connect to the database, you will need:
- to get the Postgresql driver
- fetch Heroku’s DB configuration from the DATABASE_URL environment variable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
package main
import (
_ "github.com/lib/pq"
"log"
"database/sql"
"os"
)
// Fetch the list of novels
func GetList() []*Novel {
novels := make([]*Novel, 0)
database := connect()
defer database.Close()
rows, err := database.Query("SELECT id, title, url, image_url, summary, favorite FROM novels")
if err != nil {
log.Fatalf("[x] Error when getting the list of novels. Reason: %s", err.Error())
}
for rows.Next() {
n := toNovel(rows)
if n.IsValid() {
novels = append(novels, n)
}
}
if err := rows.Err(); err != nil {
log.Fatalf("[x] Error when getting the list of novels. Reason: %s", err.Error())
}
return novels
}
// Connect to Heroku database using the OS env DATABASE_URL
func connect() *sql.DB {
dbUrl := os.Getenv("DATABASE_URL")
database, err := sql.Open("postgres", dbUrl)
if err != nil {
log.Fatalf("[x] Could not open the connection to the database. Reason: %s", err.Error())
}
return database
}
// Fetch the content of the rows and build a new novel
func toNovel(rows db.RowMapper) *Novel {
var id string
var title string
var url string
var imageUrl string
var summary string
var favorite bool
rows.Scan(&id, &title, &url, &imageUrl, &summary, &favorite)
return &Novel{
Id: id,
Title: title,
Url: url,
ImageUrl: imageUrl,
Summary: summary,
Favorite: favorite,
}
}
|