This page looks best with JavaScript enabled

Go - Building API

 ·  ☕ 4 min read  ·  ✍️ Neeraj Sidhaye · 👀... views

In this post, I will try to put together notes around GO service and REST API.

The complete source code is available on my github repo.I have created 3 branches, each branch representing different flavour of writing service.

GO api source code

Ok, let’s go ahead…

GO - WebService

GO package net/http does the job for us. It stars the sever and ready to receive request at /hello with http.HandleFun

 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
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)
// a simple http web service which is exposing /hello end point on port 7070.
func main() {

	http.HandleFunc("/hello", func(rw http.ResponseWriter, r *http.Request) {

		fmt.Println("hello GO http web service")
		data, err := ioutil.ReadAll(r.Body) // r.body - reads the request body
		if err != nil {
			http.Error(rw, "error occurred", http.StatusInternalServerError)
			return
		}

		fmt.Fprintf(rw, "HELLO %s\n", data) 
	})

	// http webservice will be listening on any ip address and on port 7070.
	http.ListenAndServe(":7070", nil) 

}

I have written another web service example, where I have created a Handler and ServeMux and then registering handler to ServeMux.

You can have a look at the code here - getProduct service

Go - REST API

GO REST API using standard go libraries. If you see the code of below product handler, you can see I have API with methods handling GET, POST and PUT.
The important point you would note here is, you will have to write a lot of code to parse URI params ( in this example) when you use go standard libraries.
Same way, there may be other scenarios when you have to keep writing code for basic boiler plate processing.

You can see the quick demo here

Click for Demo

helloservice

 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
//handler is serving httpRequest. Returning product response JSON.
func (p *Product) ServeHTTP(rw http.ResponseWriter, r *http.Request) {

	if r.Method == http.MethodGet {
		p.l.Println("handling GET")
		p.getProducts(rw, r)
		return
	}

	if r.Method == http.MethodPost {
		p.l.Println("handling POST")
		p.addProduct(rw, r)
		return
	}

	if r.Method == http.MethodPut {
		
		p.l.Println("handling PUT")
	    
	   regex := regexp.MustCompile(`/([0-9]+)`)
	   g := regex.FindAllStringSubmatch(r.URL.Path,  -1)
	   p.l.Printf("regex g group %q\n", g)

       // if true, means there are more than one id passed in the URI.
	   if len(g)!=1 { 
			p.l.Println("invalid product id in the URI")
			http.Error(rw, "Invalid Request URI", http.StatusBadRequest)
			return
	   }

	   if len(g[0]) > 2 {
		 http.Error(rw, "Invalid URI", http.StatusBadRequest)
		 return
	   }
	   
		productID := g[0][1]
		idString, err := strconv.Atoi(productID)
	     if err!=nil {
			 http.Error(rw, "Invalid id value in URI", http.StatusBadRequest)
			 return
		 }

		p.l.Println("updating product for ID ->", idString)
		p.updateProduct(idString, rw, r)
		return

	}

	// For any other methods, we are returning method not allowed
	rw.WriteHeader(http.StatusMethodNotAllowed)

}

GO - REST API using Gorilla Mux

Include Gorilla mux dependency to go.mod.

Go mod is like gradle or maven where we include dependencies.

1
2
3
require (
	github.com/gorilla/mux v1.8.0
)

Include the package gorilla mux to your go file.

1
2
3
import (
	"github.com/gorilla/mux"
)

And now we will just create our servMux from gorilla Mux and register our product handler with various endpoints for handling GET, POST, PUT, PATCH and DELETE.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
	servMux := mux.NewRouter()
	
	// registers product handler methods to serve request on api end points with specific http methods.
	getHandler := servMux.Methods(http.MethodGet).Subrouter()
	getHandler.HandleFunc("/products", productHandler.GetProducts)

	postHandler := servMux.Methods(http.MethodPost).Subrouter()
	postHandler.HandleFunc("/products", productHandler.AddProduct)

	putHandler := servMux.Methods(http.MethodPut).Subrouter()
	putHandler.HandleFunc("/products/{id:[0-9]+}", productHandler.UpdateProduct)

	patchHandler := servMux.Methods(http.MethodPatch).Subrouter()
	patchHandler.HandleFunc("/products/{id:[0-9]+}", productHandler.UpdateProductAttribute)

	deleteHandler := servMux.Methods(http.MethodDelete).Subrouter()
	deleteHandler.HandleFunc("/products/{id:[0-9]+}", productHandler.DeleteProduct)

If you see here, it becomes so easy to parse the UI params using gorilla mux lib

1
2
3
4
5
6
7
//UpdateProduct : updating a product
func (p *Product) UpdateProduct(rw http.ResponseWriter, r *http.Request) {

	p.l.Println("handling UPDATE")

	uriParams := mux.Vars(r)
	id, err := strconv.Atoi(uriParams["id"])

Take a look at the repo for details about how api is working and you can simply clone it and run locally.

GO api source code

Hope you like this short post about GO api..

Share on

{Neeraj:Sidhaye}
WRITTEN BY
Neeraj Sidhaye
I Aspire to Inspire before I Expire!