Skip to content

Instantly share code, notes, and snippets.

@melwyn95
Last active May 27, 2020 08:34
Show Gist options
  • Save melwyn95/3c7efc0b06d0eaaf578a4b883e178837 to your computer and use it in GitHub Desktop.
Save melwyn95/3c7efc0b06d0eaaf578a4b883e178837 to your computer and use it in GitHub Desktop.
Golang for Microservices
package main
//Result deines the result of a Computation
type Result struct {
product int
row, col int
}
//Compute take a Compuataion as input and writes the Result on to a channel
func Compute(row, col int, rowSlice, colSlice []int, out chan<- Result) {
n := len(rowSlice)
product := 0
for i := 0; i < n; i++ {
product += rowSlice[i] * colSlice[i]
}
r := Result{row: row, col: col, product: product}
out <- r
}
func transpose(a [][]int) [][]int {
r, c := len(a), len(a[0])
aTranspose := make([][]int, c)
for i := 0; i < c; i++ {
aTranspose[i] = make([]int, r)
for j := 0; j < r; j++ {
aTranspose[i][j] = a[j][i]
}
}
return aTranspose
}
//MultiplyMatricesGoRoutine multiples 2 matrices using go routines & channels
func MultiplyMatricesGoRoutine(a, b [][]int) (product [][]int) {
r1, c2 := len(a), len(b[0])
product = make([][]int, r1)
out := make(chan Result, r1*c2)
bTranspose := transpose(b)
for i := 0; i < r1; i++ {
product[i] = make([]int, c2)
for j := 0; j < c2; j++ {
go Compute(i, j, a[i], bTranspose[j], out)
}
}
//collection
for i := 0; i < r1; i++ {
for j := 0; j < c2; j++ {
result := <-out
product[result.row][result.col] = result.product
}
}
return product
}
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
func getNameFromQueryParams(queryString string) string {
//split by & to get a list of query params
params := strings.Split(queryString, "&")
for i := range params {
//split each param by = to get param name and param value
param := strings.Split(params[i], "=")
//name should exists & should not be empty
if param[0] == "name" && len(param[1]) > 0 {
return param[1]
}
}
return "Stranger"
}
//Greeting - hold greeting message
type Greeting struct {
Message string
}
func jsonHandler(w http.ResponseWriter, r *http.Request) {
name := getNameFromQueryParams(r.URL.RawQuery)
message := fmt.Sprintf("Hey there %s, Good Morning!!", name)
greeting := Greeting{Message: message}
json, err := json.Marshal(greeting)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("content-type", "application/json")
w.Write(json)
}
func htmlHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hey there %s, Good Morning!!<h1>", getNameFromQueryParams(r.URL.RawQuery))
}
func main() {
http.HandleFunc("/greeter/json", jsonHandler)
http.HandleFunc("/greeter/html", htmlHandler)
fmt.Println("[http] Starting http-server on port 8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}
package main
import (
"fmt"
"math/rand"
"time"
)
func generateRandomMatrix(r, c int) [][]int {
rg := rand.New(rand.NewSource(time.Now().UnixNano()))
var matrix [][]int = make([][]int, r)
for i := 0; i < r; i++ {
matrix[i] = make([]int, c)
for j := 0; j < c; j++ {
matrix[i][j] = rg.Intn(100)
}
}
return matrix
}
func main() {
a, b := generateRandomMatrix(3, 5), generateRandomMatrix(5, 3)
fmt.Println(MultiplyMatrices(a, b))
fmt.Println(MultiplyMatricesGoRoutine(a, b))
}
package main
import "testing"
const size int = 100
//BenchmarkMatricMultiplicationNormal - benchmark for normal matrix multiplication
func BenchmarkMatricMultiplicationNormal(b *testing.B) {
for i := 0; i < b.N; i++ {
a, b := generateRandomMatrix(size, size), generateRandomMatrix(size, size)
MultiplyMatrices(a, b)
}
}
//BenchmarkMatricMultiplicationGoRoutines - benchmark for concurrent matix multiplication
func BenchmarkMatricMultiplicationGoRoutines(b *testing.B) {
for i := 0; i < b.N; i++ {
a, b := generateRandomMatrix(size, size), generateRandomMatrix(size, size)
MultiplyMatricesGoRoutine(a, b)
}
}
package main
import "testing"
func getIdentityMatrix(n int) [][]int {
matrix := make([][]int, n)
for i := 0; i < n; i++ {
matrix[i] = make([]int, n)
for j := 0; j < n; j++ {
if i == j {
matrix[i][j] = 1
} else {
matrix[i][j] = 0
}
}
}
return matrix
}
func AreSquareMatricesEqual(a, b [][]int, n int) bool {
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
if a[i][j] != b[i][j] {
return false
}
}
}
return true
}
//TestMatricMultiplicationGoRoutines - test for normal matrix multiplication
func TestMatricMultiplicationNormal(t *testing.T) {
n := 3
a, b := generateRandomMatrix(n, n), getIdentityMatrix(n)
c := MultiplyMatrices(a, b)
if !AreSquareMatricesEqual(a, c, n) {
t.Errorf("[failed] Test Failed\na = %v \nc = %v", a, c)
}
}
//TestMatricMultiplicationGoRoutines - test for concurrent matix multiplication
func TestMatricMultiplicationGoRoutines(t *testing.T) {
n := 3
a, b := generateRandomMatrix(n, n), getIdentityMatrix(n)
c := MultiplyMatricesGoRoutine(a, b)
if !AreSquareMatricesEqual(a, c, n) {
t.Errorf("[failed] Test Failed\na = %v \nc = %v", a, c)
}
}
package main
//MultiplyMatrices multiples 2 matrices O(n^3)
func MultiplyMatrices(a, b [][]int) (product [][]int) {
r1, c2, r2 := len(a), len(b[0]), len(b)
product = make([][]int, r1)
for i := 0; i < r1; i++ {
product[i] = make([]int, c2)
for j := 0; j < c2; j++ {
for k := 0; k < r2; k++ {
product[i][j] += a[i][k] * b[k][j]
}
}
}
return product
}

Golang for Microservices

What is this session about?

  • Go Programming Language
  • Microservice concepts

What can you take away from the session?

  • Stand out from the crowd in the final phases of the interview process
  • Why golang? Why golang for microservices?
  • Cloud-native applications
  • Practices are followed in the industry

Go / Golang

  • Classification of programming languages
    • static vs dynamic typing | compiled vs interpreted
    • system programming vs application programming
  • Go: a systems programmng language developed by Google in 2007
  • Used by big companies like Google, Uber, product based companies, etc.
  • Designed and implemented by Ken Thompson, Rob Pike and others.
  • Features
    • Simplicity + Readability + Performance
    • Working with pointers very fun & easy in Go
    • Very opinionated design (Deliberately Simple)
    • No inheritance: prefer composition over inheritance
    • No generics
    • Garbage collected
    • Designed for Multi-core processors (Concurrency) go routines + channels
    • No cyclic dependencies in modules
    • Awesome standard library
    • Strongly opinionated about code formatting (gofmt) & code organization
  • Syntax
    • How to write go code
    • for (no while loop in Go :P), if else
    • make: slice, channels
    • structs
    • Testing & Benchmarking
  • Demo: Matrix Muliplication
  • Demo: Http-Server in under 50 lines of code

Microservices

  • Monolith vs Microserivce
  • Bulding blocks / Components of Microservice architecture
    • Docker: Containerize your application
    • CI / CD
    • Autoscaling (ECS) + Loadbalancers
    • Background / Batch processing -> Messaege Queue (Kafka) [Event driven architecture]
    • API gateway -> Routing + Auth + Rate Limiting etc.
package main
import "fmt"
func sumArray(arr [10]int) int {
sum := 0
for i := 0; i < 10; i++ {
sum += arr[i]
}
return sum
}
func digits(n int) []int {
d := []int{}
for n > 0 {
d = append(d, n%10)
n /= 10
}
return d
}
func evenOdd(arr [10]int) ([]int, []int) {
even, odd := []int{}, []int{}
for i := range arr {
if arr[i]%2 == 0 {
even = append(even, arr[i])
} else {
odd = append(odd, arr[i])
}
}
return even, odd
}
//Person represent a person
type Person struct {
name string
age uint
}
func sayHi(names chan string, out chan string) {
for name := range names {
out <- "Hi " + name
}
}
func main() {
fmt.Println("Hello World!!")
//Array, for loops (finite)
var arr [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Printf("Sum of %v = %d\n", arr, sumArray(arr))
//slice; while loop equivalent
fmt.Println(digits(12345))
//infinite loop
// for {
// fmt.Print(".")
// }
//if else -> even odd
even, odd := evenOdd(arr)
fmt.Printf("even = %v\nodd = %v\n", even, odd)
//struct
person := Person{name: "Brian May", age: 72}
fmt.Println(person)
//go routines & channels
names, out := make(chan string, 2), make(chan string, 2)
names <- "Brian May"
names <- "Freddie Mercury"
go sayHi(names, out)
go sayHi(names, out)
fmt.Println(<-out)
fmt.Println(<-out)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment