Last active
July 25, 2019 16:46
-
-
Save boseabhishek/7b9c8530be4cf9eb3443f4823fb1e5c2 to your computer and use it in GitHub Desktop.
Async parallel calls to invoke two APIs using anonymous goroutine functions and channels to pipe the response
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"time" | |
"github.com/julienschmidt/httprouter" | |
) | |
func doGet(url string) ([]byte, error) { | |
req, err := http.NewRequest("GET", url, nil) | |
if err != nil { | |
return []byte{}, fmt.Errorf("Failed to create HTTP Request %s", err) | |
} | |
var getClient = &http.Client{ | |
Timeout: time.Second * 10, | |
} | |
resp, err := getClient.Do(req) | |
if err != nil { | |
return []byte{}, fmt.Errorf("The HTTP request failed with error %s", err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
if err != nil { | |
return []byte{}, fmt.Errorf("Cannot raed response body due to %s", err) | |
} | |
if 200 != resp.StatusCode { | |
return body, fmt.Errorf("HTTP Status Not_OK %s", err) | |
} | |
return body, nil | |
} | |
func formURL(id string) string { | |
return fmt.Sprintf("https://jsonplaceholder.typicode.com/todos/%s", id) | |
} | |
func GetTodos(id string) []map[string]interface{} { | |
//create an empty response of string type | |
resp := []map[string]interface{}{} | |
//step 1: create channels which can be used to pass a string around | |
//(Channels are the pipes that connect concurrent goroutines) | |
//Channels are typed by the values they convey. | |
chn := make(chan map[string]interface{}, 2) | |
errCh := make(chan error, 2) | |
//two parallel calls | |
go consumeRequest(id, chn, errCh) | |
go consumeRequest(id, chn, errCh) | |
//ading up the contents of the channels which are string | |
for i := 0; i < 2; i++ { | |
select { | |
case err := <-errCh: | |
fmt.Println(err) | |
case r := <-chn: | |
resp = append(resp, r) | |
} | |
} | |
return resp | |
} | |
func consumeRequest(id string, out chan<- map[string]interface{}, errCh chan<- error) { | |
body, err := doGet(formURL(id)) | |
if err != nil { | |
errCh <- err | |
return | |
} | |
r := map[string]interface{}{} | |
if err := json.Unmarshal(body, &r); err != nil { | |
errCh <- err | |
return | |
} | |
out <- r | |
} | |
func TodosHandler(writer http.ResponseWriter, req *http.Request, param httprouter.Params) { | |
id := param.ByName("id") | |
res := GetTodos(id) | |
json.NewEncoder(writer).Encode(res) | |
} | |
func main() { | |
//creates a new router | |
router := httprouter.New() | |
router.GET("/todos/:id", TodosHandler) | |
log.Fatal(http.ListenAndServe(":9093", router)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment