A projecthez tartozó GitHub Repository itt található

Go Service

Az előző lépésben megírtunk egy Go Application-t, és egy go module-t, ami alkalmas arra, hogy kiírjon valamit a standard outputra.

Most szeretnénk, ha egy egyszerű Go alkalmazás helyett, lenne egy microservice, aminek az API-ját meghívhatnánk. Ez úgy nézne ki, hogy vagy a böngészőn keresztül, vagy egy egyszerű curl parannccsal küldenénk egy requestet a szerverünkhöz, amire várnánk egy választ.

Pl.: http://localhost:8081/test –> visszaadna egy választ nekünk.

Írjuk át az alkalmazásunkat, hogy egyszerű szerverként funkcionáljon.

Amikor szervert futtatunk, akkor érdemes:

  • Bekérni, hogy milyen címen és porton fusson a szerver (ehhez mi flageket fogunk használni)
  • Rendelkezni alapértelmezett (default) értékekkel, hogy ha valaki úgy dönt, hogy nem ad át egy címet és egy portot
  • Elindítani a szervert a rendelkezésünkre álló adatokkal

A main.go fájlunk az alábbi módon fog kinézni ezek után:

package main  # Továbbra is a main package-ben maradunk

import (
  "flag"      # beimportáljuk a flag packaget, hogy bekérhessünk adatokat a szerver indulásakor
  "fmt"       # ezt használjuk arra, hogy kiírassunk üzeneteket a standard outputra
  "net/http"  # ennek a segítségével indítunk el egy web szervert

  "github.com/SanFranciscobolJottem/penguin-api/pkg/handlers"  # rövidesen írunk egy handler-t amit itt beimportálunk
)

# Ha a program indításakor nem definiálnak címet és portot, ezeket az alapértelmezett értékeket fogjuk használni
const (  
	defaultAddress string = "0.0.0.0"
	defaultPort    int    = 80
)

# Ezekben a változókban fogjuk tárolni a szerver címét és a portot.
var (
	address string
	port    int
)

# A fő függvényünk, ami legelőször meghívásra kerül program indításnál
func main() {
  # Az `address` változóban fogjuk tárolni a szerver címét. Ha megadnak egy "address" paramétert program indításkor, 
  # akkor annak az értéke kerül bele. Ha nem adnak meg, akkor a `defaultAddress` értéke kerül bele. 
  # Az utolsó paraméter egy leírás a definiálható flag-ről.
  flag.StringVar(&address, "address", defaultAddress, "Server's Address")

  # Ugyanezt megcsináljuk a port bekérésekor, de itt az eredményt egy intben tároljuk
  flag.IntVar(&port, "port", defaultPort, "Server's Port")

  # Itt történik az értékek evaluálása
  flag.Parse()

  # Meghívjuk a segéd függvényünket
  runAPI()
}

# Ez a segédfüggvény felelős azért, hogy elindítsunk egy webszervert.
func runAPI() {
  # Létrehozunk egy stringet, ami tárolja a címet, egy kettőspontot és utána a portot. Pl. 127.0.0.1:8081
  fullAddress := fmt.Sprintf("%s:%d", address, port)

  # Kiiratunk egy üzenetet a standard outputra
  fmt.Printf("\n Server is running on %s", fullAddress)

  # A /test endpoint kezelését rábízzuk egy handler függvényre, amit egy másik fájlban fogunk mindjárt definiálni
  http.HandleFunc("/test", handlers.TestHandler)

  # Elindítjuk a szerverünket a megadott címen + porton
  http.ListenAndServe(fullAddress, nil)
}

Handler készítése

Ezek után létrehozunk egy két új alkönyvtárat a project gyökérkönyvtárában.

mkdir -p pkg/handlers

és létrehozunk egy új fájlt ebben a könyvtárban, handlers.go néven.

code pkg/handlers/handlers.go

A fájl tartalma pedig ez lesz:

package handlers  # a handlers packageben fog élni, erre hivatkozik a main.go fájlunk

# beimportálunk pár segéd libraryt
import (
	"fmt"     
	"net/http"
	"strconv"
)

# Ez a handler lett a main.go-ban hozzárendelve a /test endpointhoz.
# Minden handlernek kötelező fogadnia egy writer-t, amibe a válaszunkat írjuk,
# és egy Requestet, ami a bejövő requestet képviseli. 
func TestHandler(w http.ResponseWriter, r *http.Request) {
	result := getSum(r) # átadjuk a requestet egy segéd függvénynek, és eltároljuk a visszatérési értéket egy változóban
	fmt.Fprintf(w, "Hello Gyula, az eredmenyed: %v", result) # A response writerbe beleírjuk a válaszunkat, így a requester meg fogja kapni
}

# Ez a függvény bekér a requestből két változót, és az összegüket visszaküldi int típusú változóként
# a func jelzi, hogy ez egy függvény. A `getSum` a neve. `r`-nek hívjuk a beérkező Request paramétert. `int` típusú visszatérő értéket küldünk vissza. 
func getSum(r *http.Request) int {
  # Kiszedjük az a és b változó eredményét a requestből.
  # Például valaki ezt írta a böngészőjébe: http://localhost:8081/test?a=1&b=2
  params := r.URL.Query()

  # Sajnos az értékeket string-két kapjuk vissza, ezért majd át kell őket alakítanunk int típusúvá.
  a := params.Get("a")
  b := params.Get("b")

  # Ha nem adtak meg a URL-ben `a` változót, akkor `a` értéke nulla lesz.
  if a == "" {
  	a = "0"
  }

  # Ha nem adtak meg a URL-ben `b` változót, akkor `b` értéke nulla lesz.
  if b == "" {
  	b = "0"
  }

  # A string értékekből int-et csinálunk. Ha hibát kapunk (error), azt kiíratjuk a standard outputra
  aNumber, err := strconv.Atoi(a)
  if err != nil {
  	fmt.Println(err)
  }
  bNumber, _ := strconv.Atoi(b)
  if err != nil {
  	fmt.Println(err)
  }

  # A két szám összeadott értékét visszaküldjük 
  return aNumber + bNumber
}

Makefile módosítása

Mivel most már képes a Go alkalmazásunk fogadni két paramétert, ezért módosíthatjuk a Makefile-unkat az alábbi módon:

run: build
	$(BIN_LINUX) --address 127.0.0.1 --port 8081

Ezen a ponton érdemes tesztelni, hogy a szerverünk működik, a terminálban a gyökérkönyvtárból ismét használhatjuk a Makefile-t.

make run

Egy böngészben, vagy egy új terminal tab-en (ctrl + shift + o) küldhetünk egy teszt requestet a szerverünknek:

curl localhost:8081/test?a=a&b=2

A visszaérkező eredményünk pedig megjelenik a válaszban. A szervert a ctrl + c-vel tudjuk leállítani.

Go service

Visszaküldés a repositoryba

Végül pedig állítsd össze a módosításaidat és commitold őket GitHubra.

git status  # Információt ad vissza a git repo aktuális állapotáról
git add .   # a stage-re helyezi a módosított/hozzáadott fájlokat
git commit -m "Converting the Go App into a microservice" # A stage tartalmát commitolja a lokális repositoryba
git push origin main # Felpusholja a commitodat a GitHub repositoryba, aminek a UI-on is megnézheted a tartalmát