The READ part of REST API is rather simple. Fetch one row, filtered rows or all rows. The challenge is to make it dynamic.

2. Do an AJAX Request with retuning data

The AJAX Request accepts dynamic call (+path) and writes back to the HTML page target (id="data")

function api3get(path) {
var url = ""+path;
var xhr = new XMLHttpRequest();"GET", url);
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = function() {
if (xhr.readyState === 4) {
document.getElementById("data").innerHTML = this.responseText
3+4. Lookup and get SQL Query from the REST call

Instead of storing each Query in the API, the query is stored in a database (almost similar to the Postgresql view function) fetched for each request. This means easier to maintain and more generic API (fewer endpoints)

The query is fetced with an id "tsk_all" from the REST call

func Getquery(path string) string {
// get query from lookup db
var query string
err := db.QueryRow("SELECT sql_query FROM sqls WHERE sql_id=$1", path).Scan(&query)
if err != nil {
path = ""
return query

The lookup Query look like this with a parameter that is filled with JSON from the form in the next step

7+8+9. Execute the SQL Query and return data

The READ endpoint in the Go API contains both executing the query as well as return data back to the client.

package main

import (

func Get(w http.ResponseWriter, r *http.Request) {
scope, action, val := getpath(r)
var data interface{}
val, _ = url.QueryUnescape(val)

switch action {
case "id":
query := Getquery(scope + "_" + action)
data = getid(query, val)
case "all":
query := Getquery(scope + "_" + action)
data = getall(query)

json.NewEncoder(w).Encode(data) //write back to client

// return a single row
func getid(query string, val string) interface{} {
if len(query) > 0 {
row := make(map[string]interface{})
db.QueryRowx(query, val).MapScan(row)
return (row)
return nil

// query to return a list
func getall(query string) interface{} {
if len(query) > 0 {
var list []map[string]interface{}
rows, err := db.Queryx(query)

if err != nil {
log("no records")

defer rows.Close()

for rows.Next() {
row := make(map[string]interface{})
err = rows.MapScan(row)
if err != nil {
list = append(list, row)

if len(list) == 0 {
return ("norec")
return list
return nil

The data appears in the tag id="data"

<div id="data">The result</div>

All steps above put together:

The result: