Go or Golang is one of the most popular programming language in the world right now. Due to its robustness, state of the art productivity & high-level efficiency along with static typing it has become the hottest prospect these days.
Why do we need this?
Considering how popular Golang has become and its effectiveness of code execution and networking performance, consuming REST APIs is inevitable in whatever product you are trying to build and whatever problem you are trying to solve.
So let’s get started.
Before moving further I’m going to assume that you have Go installed in your system.
One of the ways to verify it is run the following command in your command prompt/ terminal,
go versionÂ
It should show something like this,
It means you have go installed and we can move forward.
First let us create an empty folder where our code will reside.
I’m calling it consume-rest-api
Now open this empty folder directory in your favorite code editor. I’ll be using VS Code for today,
Now we will create a new file called main.go,
Now open the terminal/command prompt in this directory. In this case, I will be using the integrated terminal that comes with VS Code.
Run this command,
go mod init YOUR_APP_NAME
so in our case my command will be
go mod init consume-rest-api
After running it you will see the above output.
Also there will be file generated called go.mod
As you can see it has the name of the app that we provided in the command and the go version for our application.
Now let’s go to main.go
As we can everything in go needs to be in a package, so we will write “package main” at the top of the file,
Now to consume REST APIs we will need APIs so for that purpose we will be using,
https://jsonplaceholder.typicode.com/
It is a great tool and gives us hosted predefined HTTP REST APIs to integrate and test our code.
We will be using /posts endpoint to use HTTP GET,
https://jsonplaceholder.typicode.com/posts
So let’s jump into go code now.
We will write a function called main like this,
func main() {}
We will write another method,
func getPosts() {}
We will write the implementation of get posts inside our method.
First we will write the import state just after the package line.
import "net/http"
We will need HTTP library in order to call our API.
Now inside getPosts() method we will write the following line,
response, err := http.Get("https://jsonplaceholder.typicode.com/posts")
http.Get method will take the URL as input and it can return two possible values, one is response on success and another one is err.
Let’s use these variables now to see the response.
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
First, we will check if there is error then we print the error for now. In a real-world application, we can perform some error logging and retry in this block.
Also in order to use fmt.Print we need to import fmt and os to exit as well so now our imports will look like this,
import (
"fmt"
"net/http"
"os"
)
Now if there is no error we will try to read the response from the response object like this,
responseData, err := ioutil.ReadAll(response.Body)
Again, this ioutil will need to be imported and this ReadAll method will return two possible values, one is actual response body and the other one is error object.
Now let’s read these values.
if err != nil {
fmt.Print(err)
}
fmt.Println(string(responseData))
We check the error object again, print if it's not null. After it, we will print the response data.
So our entire method should look something like this,
func getPosts() {
response,
err: = http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData,
err: = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Print(err)
}
fmt.Println(string(responseData))
}
Now we will just call this method inside our main function.
So main looks like this,
func main() {
getPosts()
}
Our entire file is something like this.
package main
import("fmt"
"io/ioutil"
"net/http"
"os")
func main() {
getPosts()
}
func getPosts() {
response,
err: = http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData,
err: = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Print(err)
}
fmt.Println(string(responseData))
}
Now we will open our terminal in the same directory again and run the following command
go run main.go
Once we press enter we should see the output of our code in the console.
As you can see we got the response from HTTP Get Endpoint and it's printed in the console.
Now let’s convert this string response into a code object that we can use further.
We will create a struct with the properties of posts.
We will create an empty file called posts.go inside a folder named models,
Let’s take a look at our posts object,
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
So according to this object our struct should have these four properties.
So our posts will look something like this,
package models
type Posts struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
}
Here string inside `` represents which property of JSON should go bind the values from.
In the above code we can see UserId property of struct is binded to userId keyword from JSON.
Now we will unmarshal our JSON.
To use our Posts struct, we have to import its package which is models, so in order to do that we will write the following line in our main.go’s import section
"consume-rest-api/models"
Name of our application defined in go.mod and after it the package name.
Now we can write the code to unmarshal the JSON,
var responseObject []models.Posts
json.Unmarshal(responseData, &responseObject)
fmt.Println(responseObject)
Here we just declared the array of Posts model, then we have used JSON library provided by go itself to call unmarshal method, which will convert the JSON data into the array of our struct type using the JSON keys that we have mentioned in our struct. After that we are just printing out the response object.
So now our entire file looks something like this.
package main
import("consume-rest-api/models"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os")
func main() {
getPosts()
}
func getPosts() {
response,
err: = http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData,
err: = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Print(err)
}
var responseObject[] models.Posts
json.Unmarshal(responseData, & responseObject)
fmt.Println(responseObject)
}
Now try to run our code again using
go run main.go
As we can see values are getting printed from our Posts object now.
Now let’s quickly see the HTTP POST endpoint as well.
func savePosts() {
post: = models.Posts {
UserId: 1,
Body: "Body",
Title: "title",
}
json_data,
err: = json.Marshal(post)
if err != nil {
fmt.Print(err)
}
response,
err: = http.Post("https://jsonplaceholder.typicode.com/posts", "application/json", bytes.NewBuffer(json_data))
if err != nil {
fmt.Print(err)
}
fmt.Println(response.StatusCode)
}
Initially, we are declaring a post object and initializing it with some values.
Now after that we are marshalling our data using JSON library’s marshal method. It will transform our code object into the JSON data that is understood by the REST APIs.
We check for errors from that method.
After that, we call the http.Post method now.
Unlike http.Get which takes just one parameter URL, post takes three parameters.
First is URL of your REST API, second is the content type. Which is application/json in our case because we are using json data type. Third parameter is the actual data that we want to send over, so we take our json data and pass it to bytes.NewBuffer method.
After that we again check for errors and print out the status code.
If everything goes well then standard response for HTTP POST API is 201 which is for entity created.
So let’s try to run our code after calling this method in main and see the output.
As we can see we are getting the response status code as 201, which means we are consuming the post API properly.
Our entire file is,
package main
import("bytes"
"consume-rest-api/models"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os")
func main() {
getPosts()
savePosts()
}
func getPosts() {
response,
err: = http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData,
err: = ioutil.ReadAll(response.Body)
if err != nil {
fmt.Print(err)
}
var responseObject[] models.Posts
json.Unmarshal(responseData, & responseObject)
//fmt.Println(responseObject)
}
func savePosts() {
post: = models.Posts {
UserId: 1,
Body: "Body",
Title: "title",
}
json_data,
err: = json.Marshal(post)
if err != nil {
fmt.Print(err)
}
response,
err: = http.Post("https://jsonplaceholder.typicode.com/posts", "application/json", bytes.NewBuffer(json_data))
if err != nil {
fmt.Print(err)
}
fmt.Println(response.StatusCode)
}
Summary
In today’s article, we have seen how to consume REST APIs in golang. We consumed HTTP GET method and HTTP Post method here.
If you wish to see the code please click here!