Now that our Postgres DB is up and running, we now have to implement the package that we’ll use to communicate to this database.
Create a new directory within your internal
directory called database
. Within that create a new file called database.go
:
package database
import (
"fmt"
"os"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
// NewDatabase - returns a pointer to a new database connection
func NewDatabase() (*gorm.DB, error) {
return nil, nil
}
Now, within the NewDatabase
function, we’ll want to setup a connection and then ping that connection to ensure it’s working as intended.
In order to get the configuration, we never want to hardcode anything so we’ll leverage the os
package and pick all of the connection information from environment variables.
Once we’ve got those environment variables set up, let’s use the GORM package with the postgres driver in order to create a pointer to a DB connection.
Once we’ve got this, we can then ping the database and this should tell us whether or not we’ve been successful in connecting.
package database
import (
"fmt"
"os"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
// NewDatabase - returns a pointer to a new database connection
func NewDatabase() (*gorm.DB, error) {
dbUsername := os.Getenv("DB_USERNAME")
dbPassword := os.Getenv("DB_PASSWORD")
dbHost := os.Getenv("DB_HOST")
dbDatabaseName := os.Getenv("DB_DATABASE_NAME")
dbPort := os.Getenv("DB_PORT")
// dbConnectionString := dbUsername + ":" + dbPassword + "@tcp(" + dbHost + ":" + strconv.Itoa(dbPort) + ")/" + dbDatabaseName
connectionString := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=disable", dbHost, dbPort, dbUsername, dbDatabaseName, dbPassword)
fmt.Println(connectionString)
db, err := gorm.Open("postgres", connectionString)
if err != nil {
return db, err
}
if err := db.DB().Ping(); err != nil {
return db, err
}
return db, nil
}
With this in place, let’s jump back into the cmd/server/main.go
and call this newly defined NewDatabase
function:
// App - the struct which contains things like pointers
// to database connections
type App struct{}
// Run - sets up our application
func (app *App) Run() error {
fmt.Println("Setting Up Our APP")
var err error
db, err := database.NewDatabase()
if err != nil {
return err
}
handler := transportHTTP.NewHandler(commentService)
handler.SetupRoutes()
if err := http.ListenAndServe(":8080", handler.Router); err != nil {
fmt.Println("Failed to set up server")
return err
}
return nil
}
With this in place, let’s jump down into the terminal and run the following:
$ export DB_USERNAME=postgres
$ export DB_PASSWORD=postgres
$ export DB_TABLE=postgres
$ export DB_PORT=5432
$ export DB_DB=postgres
$ go run cmd/server/main.go
You should see that the application picks up these underlying environment variables and is able to connect to our running Postgres database without throwing any errors!
Erratum
- The
DB_TABLE
should be replaced withDB_DATABASE_NAME
and the variable you use in the constructor should also be changed todbDatabaseName
.
Since releasing this course, gorm
have made some changes to how a connection is established. This code below, provided very kindly by Dmitry, should reflect how
you can establish a connection with the latest version of their package.
connectionString := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s", dbHost, dbPort, dbUsername, dbDatabaseName, dbPassword)
db, err := gorm.Open(postgres.Open(connectionString), &gorm.Config{})
if err != nil {
return db, err
}
postgresDb, err := db.DB()
if err != nil {
return db, err
}
if err := postgresDb.Ping(); err != nil {
return db, err
}