Venkata this one’s for you 😀
It took me the rest of the afternoon, but here is a pretty simple GET
request example, using a user-defined ORDS API. This API is derived from one of our LiveLabs, a Python + JavaScript application. But this particular scenario pretty well exemplifies what we discussed in our presentation yesterday—that the RESTful framework makes your backend code much more language-agnostic. With a few tweaks, I was able to “port” this over to Go.
ORDS example API
The ORDS API I’m working with looks like this on the back end (this is our REST Workshop; where you build ORDS APIs):

More formally, it looks like this:
SELECT DISTINCT
GENRE
FROM
MOVIE,
JSON_TABLE ( GENRES, '$[*]'
COLUMNS (
GENRE PATH '$'
)
)
ORDER BY
1 ASC
The MOVIE
table I’m calling upon consists of various data types, but the target GENRE
In this case, the column is a JSON object that actually contains an array. So, all I’m doing is returning the unique genres (i.e., removing duplicates) from a table of thousands of movies. What is nice about this approach is that all my SQL and PL/SQL stay in the database. All my application’s code needs now is an endpoint.
If I don’t want to keep pinging that endpoint, I can always just use a JSON document as a proxy for the endpoint. And if I just point my browser to that URI (i.e. ORDS API), here is what the results look like (I had to take two screenshots to capture everything):


When you are looking at these results, it’s best to focus on the “root” key:value
pairs of the ORDS response. For a fairly standard ORDS GET
request, the response body will consist of:
items
hasMore
limit
offset
count
, andlinks
When I collapse my example, I am left with the following:
{
"items": [
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 24,
"links": [
]
}
Note: Theitems
will be an array, as will thelinks
.
A caveat to this is when/if you choose to Auto-REST enable an object, the result will look mostly the same. However, ORDS adds a self-referential link to each result. But those links
are an array, too.
Regardless, it shouldn’t affect how you approach this in Go. The struct
of those types are the same: Items []Items json:"items"
and Links []Links json:"links"
, respectively. Compare this auto-REST-enabled result to the one above:
Worth noting: The image below is using a different endpoint. Its basically doing a "select * from movies;
" on theMOVIES
table. Hence, why it looks a little different. But you should still be able to see what I am talking about. If you want to learn more about ORDS Auto-REST, then check this out.

rel
” link. That is how Auto-REST would look, this is expected.Go time
Coming from Python and PL/SQL, along with some JavaScript, I found Go to be extremely enjoyable. I get the gist of how you define the types and structures of “things.” I haven’t even bothered to look at the documentation yet; I didn’t even need to. It was easy to follow along using the two tutorials I found (here and here). After a few minutes of debugging (which is quite intuitive in Go, actually), I had my code working.
Actually, once I figured out the syntax and Go idiosyncracies, it wasn’t much of an effort to create this simple example.
Here is the Go code that I came up with:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
type Response struct {
Items []Items `json:"items"`
Hasmore bool `json:"hasMore"`
Limit int `json:"limit"`
Offset int `json:"offset"`
Count int `json:"count"`
Links []Links `json:"links"`
}
type Items struct {
Genre string `json:"genre"`
}
type Links struct {
Rel string `json:"rel"`
Href string `json:"href"`
}
func main() {
response, err := http.Get("http://localhost:8081/ords/ordsdemo/mymovies/movie-genre")
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
var responseObject Response
json.Unmarshal(responseData, &responseObject)
for i := 0; i < len(responseObject.Items); i++ {
fmt.Println(responseObject.Items[i].Genre)
}
fmt.Println(responseObject.Hasmore)
fmt.Println(responseObject.Limit)
fmt.Println(responseObject.Offset)
fmt.Println(responseObject.Count)
for i := 0; i < len(responseObject.Links); i++ {
fmt.Println(responseObject.Links[i].Rel + responseObject.Links[i].Href)
}
}

If you know Go, then I’m not teaching you anything that you don’t already know. You probably know the libraries I’m using. However, I think it is worth pointing out a few ORDS-specific things.
When it comes to the items
and the links
they are always going to be an array. So you’ll need to account for that when you are defining the structures (aka struct
) for your user-defined types (let me know if this terminology is correct, it just seems so intuitive, so I’m going with it).
Here are some other things to consider:
hasMore
is a Boolean; orbool
in Go. It’s also going to be eithertrue
orfalse
.True
means there are more results (so you can page forward if you want).False
means there are no more results.
limit
just means how many results you should expect. In my case, 25 results (that is our default, but you can adjust this when you build your APIs).- Another way to look at this is that my pagination is set to 25 results per page.
offset
andlimit
are kind of interdependent. If you are on the first page then your offset will be= 0
. But if you wanted to view your second “page” or set of results, then you’d set youroffset = 25
.- And because your
limit = 25
then you’d see results26-50
.
- And because your
- The
count
is just the total results per page, or 25 in this case (hypothetically, if you were to make it to the end of your results set, it would probably not be exactly 25, something to keep in mind).
Here is a complete JSON object of my first results (if you want to play around with it until you get ORDS up and running):
{
"items": [
{
"genre": "Action"
},
{
"genre": "Adventure"
},
{
"genre": "Animation"
},
{
"genre": "Biography"
},
{
"genre": "Comedy"
},
{
"genre": "Crime"
},
{
"genre": "Documentary"
},
{
"genre": "Drama"
},
{
"genre": "Family"
},
{
"genre": "Fantasy"
},
{
"genre": "Film-Noir"
},
{
"genre": "History"
},
{
"genre": "Horror"
},
{
"genre": "Lifestyle"
},
{
"genre": "Musical"
},
{
"genre": "Mystery"
},
{
"genre": "Reality-TV"
},
{
"genre": "Romance"
},
{
"genre": "Sci-Fi"
},
{
"genre": "Sport"
},
{
"genre": "Thriller"
},
{
"genre": "Unknown"
},
{
"genre": "War"
},
{
"genre": "Western"
}
],
"hasMore": false,
"limit": 25,
"offset": 0,
"count": 24,
"links": [
{
"rel": "self",
"href": "http://localhost:8081/ords/ordsdemo/mymovies/movie-genre"
},
{
"rel": "describedby",
"href": "http://localhost:8081/ords/ordsdemo/metadata-catalog/mymovies/item"
},
{
"rel": "first",
"href": "http://localhost:8081/ords/ordsdemo/mymovies/movie-genre"
}
]
}
All the code you see here is also in my blog post code repo too. There are other examples there too!
Also, huge thanks for asking about Go. It gave me an excuse to start learning it. I think I might be a Go fanboi now 🫣!
And for all others reading:
Follow
And don’t forget to follow, like, subscribe, share, taunt, troll, or stalk me!