What is this article about?
Import
Debug
Variables and Declarations
Function Declarations
Data Type
Structure, enum, class
Maps, Arrays and Slices
Interfaces
Concurrency
Pointer
How to create a routes ( Storing routes, static routes, dynamic routes, Forwarding routes… )
Working with web handlers, requests, and ResponseWriter instances: parse request data, response JSON
Making a middleware in Golang
Handling errors and the Error interface in Golang
Concurrency in Golang
Microservice and Monolithic with Golang, java, nodejs
Using structures and closures for stateful handlers
Validating input for Go structures and user inputs
Rendering and content negotiation
Implementing and using middleware
Building a reverse proxy application
About GRPC clients

Variables and Declarations

It is quite simple to define a variables, look the example code below
Example Code


package main

import "fmt"

func main() {

// `var` declares 1 or more variables.
var a = "initial"
fmt.Println(a)

// You can declare multiple variables at once.
var b, c int = 1, 2
fmt.Println(b, c)

// Go will infer the type of initialized variables.
var d = true
fmt.Println(d)

// Variables declared without a corresponding
// initialization are _zero-valued_. For example, the
// zero value for an `int` is `0`.
var e int
fmt.Println(e)

// The `:=` syntax is shorthand for declaring and
// initializing a variable, e.g. for
// `var f string = "apple"` in this case.
f := "apple"
fmt.Println(f)
}

Declaring and Calling Functions in Golang

In Golang, we declare a function using the func keyword. A function has a name, a list of comma-separated input parameters along with their types, the result type(s), and a body.
Following is an example of a simple function called avg that takes two input parameters of type float64 and returns the average of the inputs. The result is also of type float64:
func avg(x float64, y float64) float64 {
return (x + y) / 2
}

Now, calling a function is very simple. You just need to pass the required number of parameters to the function like this:
avg(6.56, 13.44)

Here is an example to call func sum and average:


package main
import "fmt"

func avg(x float64, y float64) float64 {
return (x + y) / 2
}
func sum(x float64, y float64) float64 {
return x + y
}

func main() {
x := 5.75
y := 6.25

result := avg(x, y)

fmt.Printf("Average of %.2f and %.2f = %.2f\n", x, y, result)

sum := sum(x,y)
fmt.Printf("Sum of %.2f and %.2f = %.2f\n", x, y, sum )
}

//go run func.go

What is an interface in Golang ?

Interfaces
An interface type is defined as a set of method signatures.
A value of interface type can hold any value that implements those methods.
It is a kind of protocol
Example

type Abser interface {
	Abs() float64
}

How to create a web server

Here, we use the “net/http” package
The default port is 8080
Look the example code below



package main

import (
"fmt"
"log"
"net/http"
)
func main() {
// http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request){
// fmt.Fprintf(w, "Hello!")
// })
http.HandleFunc("/hello", helloHandler) // Update this line of code

fmt.Printf("Starting server at port 8080\n")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/hello" {
http.Error(w, "404 not found.", http.StatusNotFound)
return
}

if r.Method != "GET" {
http.Error(w, "Method is not supported.", http.StatusNotFound)
return
}

fmt.Fprintf(w, "Hello! My name is Huy ")
}



Run the code and do a request on localhost:8080/hello, you will see this

Screen Shot 2021-03-11 at 10.26.26 AM

How to create a routes

How to create a Storing routes

How to create a static routes

How to create a dynamic routes

How to create a Forwarding routes

How to get data from API request

// File: main.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

type Person struct {
    Name string
    Age  int
}

func personCreate(w http.ResponseWriter, r *http.Request) {
    // Declare a new Person struct.
    var p Person

    // Try to decode the request body into the struct. If there is an error,
    // respond to the client with the error message and a 400 status code.
    err := json.NewDecoder(r.Body).Decode(&p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // Do something with the Person struct...
    fmt.Fprintf(w, "Person: %+v", p)
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/person/create", personCreate)

    err := http.ListenAndServe(":4000", mux)
    log.Fatal(err)
}

Run the go file above
go run main.go
Then, try to test it with a curl

/* test curl
curl --location --request POST 'localhost:4000/person/create' \
--header 'X-Access-Token: xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{"Name":"Tôi là ABC", "Age": 40}'
*/

The rusult is like below
Screen Shot 2021-03-14 at 6.02.16 PM

How to response a JSON

Use “encoding/json”
and write to http response
For example

package main

import (
  "encoding/json"
  "net/http"
  "log"
)

type Profile struct {
  Name    string
  Hobbies []string
}

func main() {
  http.HandleFunc("/", foo)
  log.Println("Starting server on port 4000...")
  http.ListenAndServe(":4000", nil)

}

func foo(w http.ResponseWriter, r *http.Request) {
  profile := Profile{"Alex", []string{"snowboarding", "programming"}}

  js, err := json.Marshal(profile)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }

  w.Header().Set("Content-Type", "application/json")
  w.Write(js)
}
/* test curl
curl --location --request POST 'localhost:4000' \
--header 'X-Access-Token: xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{"Name":"Tôi là ABC", "Age": 40}'
*/

Concurrency in Golang

Handling errors and the Error interface in Golang

Working with web handlers, requests, and ResponseWriter instances

Making a middleware in Golang

A middleware handler is simply an http.Handler that wraps another http.Handler to do some pre- and/or post-processing of the request. It’s called “middleware” because it sits in the middle between the Go web server and the actual handler.
middleware_golang

//File: main.go
package main

import (
  "log"
  "net/http"
)

func middlewareOne(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    log.Println("Executing middlewareOne")
    next.ServeHTTP(w, r)
    log.Println("Executing middlewareOne again")
  })
}

func middlewareTwo(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    log.Println("Executing middlewareTwo")
    if r.URL.Path == "/foo" {
      return
    }

    next.ServeHTTP(w, r)
    log.Println("Executing middlewareTwo again")
  })
}

func final(w http.ResponseWriter, r *http.Request) {
  log.Println("Executing finalHandler")
  w.Write([]byte("OK"))
}

func main() {
  mux := http.NewServeMux()

  finalHandler := http.HandlerFunc(final)
  mux.Handle("/", middlewareOne(middlewareTwo(finalHandler)))

  log.Println("Listening on :3000...")
  err := http.ListenAndServe(":3000", mux)
  log.Fatal(err)
}  

Microservice and Monolithic with Golang, java, nodejs

monolithic-and-microservices-architecture

Here we can have a look of the big picture
Architecture-Of-Microservices-Microservice-Architecture-Edureka

Microservice-Architecture-Of-UBER-Microservice-Architecture-Edureka-768x762
(Example of Microservice Architecture of Uber – Microservice Architecture.)

Building a reverse proxy application

Create a file name process.go

package proxy

import (
    "bytes"
    "net/http"
    "net/url"
)

// ProcessRequest modifies the request in accordnance
// with Proxy settings
func (p *Proxy) ProcessRequest(r *http.Request) error {
    proxyURLRaw := p.BaseURL + r.URL.String()

    proxyURL, err := url.Parse(proxyURLRaw)
    if err != nil {
        return err
    }
    r.URL = proxyURL
    r.Host = proxyURL.Host
    r.RequestURI = ""
    return nil
}

// CopyResponse takes the client response and writes everything
// to the ResponseWriter in the original handler
func CopyResponse(w http.ResponseWriter, resp *http.Response) {
    var out bytes.Buffer
    out.ReadFrom(resp.Body)

    for key, values := range resp.Header {
        for _, value := range values {
        w.Header().Add(key, value)
        }
    }

    w.WriteHeader(resp.StatusCode)
    w.Write(out.Bytes())
}

Create another file name proxy.go

package proxy

import (
    "log"
    "net/http"
)

// Proxy holds our configured client
// and BaseURL to proxy to”
type Proxy struct {
    Client *http.Client
    BaseURL string
}

// ServeHTTP means that proxy implements the Handler interface
// It manipulates the request, forwards it to BaseURL, then 
// returns the response
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if err := p.ProcessRequest(r); err != nil {
        log.Printf("error occurred during process request: %s", 
        err.Error())
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    resp, err := p.Client.Do(r)
    if err != nil {
        log.Printf("error occurred during client operation: 
        %s", err.Error())
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    defer resp.Body.Close()
    CopyResponse(w, resp)
}


Finally, a main.go

package main

import (
    "fmt"
    "net/http"
    "proxy"
)

func main() {
  p := &proxy.Proxy{
      Client: http.DefaultClient,
      BaseURL: "https://www.golang.org",
  }
  http.Handle("/", p)
  fmt.Println("Listening on port :3333")
  err := http.ListenAndServe(":3333", nil)
  panic(err)
}

About GRPC clients

GRPC is a high-performance RPC framework that is built using protocol buffers (https://developers.google.com/protocol-buffers) and HTTP/2 (https://http2.github.io). Creating a GRPC client in Go involves many of the same intricacies as working with Go HTTP clients

# Keyword
OAuth2
NoSQL with MongoDB
WEB Clients and APIs
REST
gRPC
parallel and async request
interface
connect database
database handler
validate user input: don’t ever trust user input
Test tool

Working with web handlers, requests, and ResponseWriter instances
Using structures and closures for stateful handlers
Validating input for Go structures and user inputs
Rendering and content negotiation
Implementing and using middleware
Building a reverse proxy application
Exporting GRPC as a JSON API
Using Kafka with Sarama
GoFlow
Consumer and producer
Serverless
Apex, Lambda, AWS Lambda
Memory allocation and heap management

Reference:
https://openmymind.net/The-Little-Go-Book/
Download ebook Go here

About the Author

Trần Huy

View all author's posts

Bài viết khác

Backend xử lý với dữ liệu người dùng tải lên như thế nào?

Khi người dùng tải lên dữ liệu (file, hình ảnh, video, v.v.), backend thường xử lý dữ liệu này qua các bước sau: Nhận dữ liệu  Qua API: Backend nhận dữ liệu từ HTTP request (thường là POST hoặc PUT). Ví dụ: sử dụng multipart/form-data cho file. Xác thực dữ liệu Kiểm tra định dạng: […]

MinIO

MinIO là gì? MinIO là một giải pháp lưu trữ đối tượng (object storage) mã nguồn mở, tương thích với API của Amazon S3. Nó được thiết kế để lưu trữ và quản lý dữ liệu phi cấu trúc như hình ảnh, video, tài liệu, và các tệp tin lớn khác. Dung lượng của 1 object […]

Relational Database Design Principle

1-1 1-n n-n   https://nexwebsites.com/database/database-design/  

Laravel

Laravel là gì? Laravel là một framework PHP mã nguồn mở miễn phí được phát hành lần đầu tiên vào năm 2011. Taylor Otwell đã tạo ra Laravel nhằm giúp các Developer xây dựng các ứng dụng web bằng cách sử dụng mẫu kiến ​​trúc Model-View-Controller (MVC). Mô hình Model-View-Controller (MVC) trong Laravel: 1. Model […]

PHP

PHP là gì? PHP là từ viết tắt của thuật ngữ Personal Home Page và hiện nay đang có tên Hypertext Preprocessor. Đây là một dạng mã lệnh hoặc một chuỗi ngôn ngữ kịch bản. Trong đó, ngôn ngữ PHP chủ yếu được phát triển để dành cho những ứng dụng nằm trên máy chủ. Mỗi […]

Build for global scale: AFK scale cube and basic rule to build an application for global scale

REF https://akfpartners.com/growth-blog/scale-cube