Go Lang and PostgreSQL Web App with MVC Pattern Part 4
Introduction
Throughout this multi-part tutorial, we’ve been demonstrating how to build a Go Lang and PostgreSQL web app with the MVC pattern. In the previous article, we tested our application and confirmed that the web app’s initial configuration was working properly. We’ll continue working on the application in this installment of the series, creating some additional functionality for our web app such as displaying a single record as well as updating, deleting and inserting new records.
Prerequisite
Before you complete any of the steps outlined in this article, be sure that you’ve already worked through the first three articles in the series.
Retrieve a Single Record in PostgreSQL using Go Lang
Let’s start by updating our main application with the routes and functions that we’ll be using in this tutorial:
1 2 3 4 5 | http.HandleFunc("/", index) http.HandleFunc("/list", model.PatientIndex) http.HandleFunc("/patient/show", model.PatientShow) http.ListenAndServe(":8080", nil) |
The code shown above simply calls the functions inside the model package whenever a request matches the route specified within the
http.HandleFunct()
method.This line of code will invoke the function within the model package for showing a single patient record:
http.HandleFunc("/patient/show", model.PatientShow)
.
Controller for Showing a PostgreSQL Single Record
In this section, we’ll create a function within our handler.go controller. We’ll use the code shown below to accomplish this task:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | func PatientShow(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed) return } patient, err := SinglePatient(r) switch { case err == sql.ErrNoRows: http.NotFound(w, r) return case err != nil: http.Error(w, http.StatusText(500), http.StatusInternalServerError) return } config.TPL.ExecuteTemplate(w, "show.gohtml", patient) } |
This code handles the request from the main.go file, that we created earlier. It simply calls the function SinglePatient(r)
from the models.go file that handles the application’s business logic. Note that this function requires a parameter, which is the request. The result returned from the function is stored in the variable patient
and is presented in the template showpatient.gohtml
.
The Model for Showing a PostgreSQL Record
We just finished creating the controller for showing a single record; now we’ll start working on the function that handles that request in the models.go file. We’ll name this function SinglePatient(r)
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | func SinglePatient(r *http.Request) (Patient, error) { patient := Patient{} patient_id := r.FormValue("patient_id") if patient_id == "" { return bk, errors.New("400. Bad Request.") } row := config.DB.QueryRow("SELECT * FROM tb_patientinfo WHERE patient_id = $1", patient_id) err := row.Scan(&patient.Patient_id, &patient.Name, &patient.Lastname, &patient.Gender, &patient.Age) if err != nil { return patient, err } return patient, nil } |
- This code will fetch a single record that matches whatever criteria is specified in the
SELECT
operation. It will then return thepatient
object.
Note: We’ll need to update the index.gohtml
View link using the following line of HTML:
This will pass the value of the Patient_id
as a parameter to the following URL” /patient/show
. The functions we created earlier will then be triggered.
Configuring the front-end
In this section, we’ll be creating the page that will display the record that we retrieved with the help of the models.go file:
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 62 63 64 65 66 67 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Patient Information</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" /> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous" ></script> </head> <body> <div class="container mb-6"> <form class="mt-5"> <h2>Patient's Information</h2> <div class="form-group row"> <label for="name" class="col-sm-2 col-form-label">Name</label> <div class="col-sm-10"> <input type="text" class="form-control" id="name" value="{{.Name}} {{.Lastname}}" disabled /> </div> </div> <div class="form-group row"> <label for="gender" class="col-sm-2 col-form-label">Gender</label> <div class="col-sm-10"> <input type="text" class="form-control" id="gender" value="{{.Gender}}" disabled /> </div> </div> <div class="form-group row"> <label for="age" class="col-sm-2 col-form-label">Age</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" value="{{.Age}}" disabled /> </div> </div> <div class="form-group row"> <div class="col-sm-10 offset-sm-2"> <a class="btn btn-primary" href="/"> « Patient Listing</a> </div> </div> </form> </div> </body> </html> |
Notice that we use the “.” notation in our code to display the data.
We can now test out our application. First, run the following command in the terminal:
go run main.go
.Next, open up a browser and enter the following URL in the address bar: ‘localhost:8080/list’.
Then click the View</kbd for the record you want to view.
You should see something like the following:
Conclusion
If you've been following along with each article in this multi-part tutorial series, you know that we've made a lot of progress on our web application. Throughout this series, we've been walking through every step involved in building a Go Lang and PostgreSQL web app using the MVC pattern. This article picked up where the last one left off, explaining how to retrieve a single record in PostgreSQL using Go Lang. Stay tuned for more step-by-step instructions in the next article, and continue following along to complete your own Go Lang and PostgreSQL web app.
The Code
We looked at quite a bit of code in this tutorial, and we modified a few different files. Shown below is the code:
The main.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package main import ( "html/template" "net/http" "patientinfo/model" _ "github.com/lib/pq" ) // package level scope, which means it can be access anywhere in this packager. var tpl *template.Template func main() { http.HandleFunc("/", index) http.HandleFunc("/list", model.PatientIndex) http.HandleFunc("/patient/show", model.PatientShow) http.ListenAndServe(":8080", nil) } func index(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/list", http.StatusSeeOther) } |
The index.gohtml
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 62 | <!DOCTYPE html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Create Patient</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href=""> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> </head> <body> <!--[if lt IE 7]> <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p> <![endif]--> <div class="container mt-4"> <h1>Patients Listing</h1> <table class="table table-sm table-bordered "> <thead class="thead-dark"> <tr> <th>id</th> <th>Name</th> <th>Last Name</th> <th>Gender</th> <th>Age</th> <th> </th> <th scope="col" colspan="3">Action</th> </tr> </thead> {{range .}} <tbody id="myTable"> <tr> <td>{{.Patient_id}}</td> <td>{{.Name}}</td> <td>{{.Lastname}}</td> <td>{{.Gender}}</td> <td>{{.Age}}</td> <td><a class="action" href="/patient/show?id={{.Patient_id}}">View</a></td> <td><a class="action" href="">Edit</a></td> <td><a class="action" href="">Delete</a></td> </tr> </tbody> {{end}} </table> </div> <script src="" async defer></script> </body> </html> |
The patient.gohtml
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 62 63 64 65 66 67 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Patient Information</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" /> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous" ></script> </head> <body> <div class="container mb-6"> <form class="mt-5"> <h2>Patient's Information</h2> <div class="form-group row"> <label for="name" class="col-sm-2 col-form-label">Name</label> <div class="col-sm-10"> <input type="text" class="form-control" id="name" value="{{.Name}} {{.Lastname}}" disabled /> </div> </div> <div class="form-group row"> <label for="gender" class="col-sm-2 col-form-label">Gender</label> <div class="col-sm-10"> <input type="text" class="form-control" id="gender" value="{{.Gender}}" disabled /> </div> </div> <div class="form-group row"> <label for="age" class="col-sm-2 col-form-label">Age</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" value="{{.Age}}" disabled /> </div> </div> <div class="form-group row"> <div class="col-sm-10 offset-sm-2"> <a class="btn btn-primary" href="/"> « Patient Listing</a> </div> </div> </form> </div> </body> </html> |
The models.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | func SinglePatient(r *http.Request) (Patient, error) { patient := Patient{} pID := r.FormValue("id") if pID == "" { return patient, errors.New("400. Bad Request.") } row := config.DB.QueryRow("SELECT * FROM tbl_patientinfo WHERE patient_id = $1", pID) err := row.Scan(&patient.Patient_id, &patient.Name, &patient.Lastname, &patient.Gender, &patient.Age) if err != nil { return patient, err } return patient, nil } |
The handler.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | func PatientShow(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed) return } patient, err := SinglePatient(r) switch { case err == sql.ErrNoRows: http.NotFound(w, r) return case err != nil: http.Error(w, http.StatusText(500), http.StatusInternalServerError) return } config.TPL.ExecuteTemplate(w, "patient.gohtml", patient) } |
Pilot the ObjectRocket Platform Free!
Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.
Get Started