I Go (went) a step further—http and other things to consume an API service. What would it take to call an API which returns a list of records in JSON? In .NET, it takes a few lines of code.
Scenario: Display a list of employees—Id, First Name, Last Name, and Joined Date—from a protected API—of a company. The returned value might contain more fields than necessary.
- Id: integer
- First Name and Last Name: string
- Joined Date: Date Time
First thing first, create a file http.go
and write some code. To work with http
, Go supplies the net/http
package.
package main
import (
"fmt"
"net/http"
)
func main() {
fmt.Println("Connecting to the API ...")
const url = "https://xxxcompany.com/api/employees"
const accessToken = "base64 access token"
fmt.Println("Base Address: ", url)
fmt.Println("Access Token: ", accessToken)
// Issue a default request but will not work because of the missing access token
resp, err := http.Get(url)
if err != nil {
fmt.Println("Cannot connect the API: ", err)
return
}
// Close the body at the end of the execution
defer resp.Body.Close()
}
Nothing’s fancy! I took them from the Go http package. When invoking a HTTP call, Go returns a response with an error if there is a connection problem. Go suggests that we must always check for error before usage—a good practice.
The above code will return a 401 status code—Not Authorized. I need to attach the access token to the request. To manipulate the request, I need to create it by myself and ask Go to send it. It is quite easy.
// Create a custom request with custom headers
resq, err := http.NewRequest(http.MethodGet, url, nil)
resq.Header.Add("x-access-token", accessToken)
// Send the request using the default client supplied by the http
resp, err := http.DefaultClient.Do(resq)
if err != nil {
fmt.Println("Cannot connect the API: ", err)
return
}
What did I get from resp.Body
? A binary stream.
binary, error:= ioutil.RealAll(resp.Body)
But I need a list of employees which is in JSON format. Go gives me the encoding/json
package to decode from binary, represented data in JSON format, to object—struct in Go. So I define an Employee struct
—custom data type—to hold the result. The Employee struct has JoinedDate
which is a date time—time
package is supplied to deal with time.
import (
"encoding/json"
"fmt"
"net/http"
"time"
)
// Existing code
// Employee
type Employee struct {
Id int
FirstName string
LastName string
JoinedDate time.Time
}
And it’s time for gardening—decode the binary stream into list of employees
// Create a decoder with passing the io reader from resp.Body
decoder := json.NewDecoder(resp.Body)
// Prepare an empty array of employees
employees := make([]Employee, 0)
// Decode, pass the pointer to the employees
decoder.Decode(&employees)
// Print the result
fmt.Println(employees)
Put them all together, I have a working program. Run go run http.go
and feel good.
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
)
func main() {
fmt.Println("Connecting to the API ...")
const url = "https://xxxcompany.com/api/employees"
const accessToken = "base64 access token"
fmt.Println("Base Address: ", url)
fmt.Println("Access Token: ", accessToken)
// Create a custom request with custom headers
resq, err := http.NewRequest(http.MethodGet, url, nil)
resq.Header.Add("x-access-token", accessToken)
// Send the request using the default client supplied by the http
resp, err := http.DefaultClient.Do(resq)
if err != nil {
fmt.Println("Cannot connect the API: ", err)
return
}
// Close the body at the end of the execution
defer resp.Body.Close()
// Create a decoder with passing the io reader from resp.Body
decoder := json.NewDecoder(resp.Body)
// Prepare an empty array of employees
employees := make([]Employee, 0)
// Decode, pass the pointer to the employees
decoder.Decode(&employees)
// Print the result
fmt.Println(employees)
}
// Employee
type Employee struct {
Id int
FirstName string
LastName string
JoinedDate time.Time
}
Go where? One step further.
- 3 new packages:
net/http
,encoding/json
,time
- Create custom http requests
- Define a new type via struct—class in C#
- Decode from binary stream—JSON data—to an array of object
- Use
make
method to create an object from a type
It makes my day, especially for the weekend!