A Go modul, a saját tengerpartod

go modul

Beszéltünk róla, hogy a Go forráskód leginkább a $GOPATH/src alatt található, de az SFJ-s tutorialok keretén belül leginkább modulokat fogunk létrehozni.

Ha a $GOPATH könyvtárra a Go tengerpartjaként tekintünk, ahol különböző projectjeid egyféle homokvárként léteznek, akkor a Go Modulodra tekinthetsz egyfajta privát tengerpartként, ami csak és kizárólag egy projectet tartalmaz, és bárhol élhet a gépeden.

Amikor a go mod init [project_nev] parancsot használod, akkor abban a könyvtárban hozod létre a saját tengerpartodat, amiben ezt a parancsot futtattad. Innentől fogva az alkönyvtárakban létrehozott .go fájlok felismerik egymást a modul részeként, és tudnak egymás függvényeire hivatkozni, ha a package után beimportálod őket.

package main

import(
  "[modulom]/[masik-packagem]"
)

A Go-ban vannak konvenciók, amelyek egyfajta ajánlásként léteznek. Képzeld el őket úgy, mint az edzőtermi etikettet. Például, ha végeztél egy gép használatával, utána illik letörölni azokat a részeket, amikhez hozzáértél, mielőtt átadod másnak a futópadot. Nem fogsz börtönbe kerülni, ha nem követed a konditerem etikettjét, de határozottan udvariatlan figyelmen kívül hagyni.

Ilyen konvenció például, hogy a változókat camelCase módon nevezzük el, vagy hogy a futtatható package külön mappában él a segéd packagektől.


go packagek

Futtatható és segéd package-k

Csak egy futtatható package van, és azt main package-nek hívjuk. A main package-ben a main függvény kerül meghívásra a Go compiler által.

De a Go kódod számtalan olyan dolgot csinálhat, ami specifikus valamilyen szempontból. Ha a main package-en kívülre teszed őket, de a main package által meghívhatóak lesznek, akkor gyakorlatilag segéd package-eket hozol létre.

Például lehet, hogy webszervert akarsz készíteni. A szervert elindító kódot, nem biztos, hogy a main package-be szeretnéd tenni. Létrehozhatsz például neki egy server package-t.

Ha a szervered kommunikálni fog a Discorddal például, vagy a Facebook Messengerrel, akkor furcsa lenne az ezekkel kapcsolatos kód fájlkat a szerver package-be tenni, akkor is, ha a szervered kommunikál velük. Érdemes tehát belegondolni, hogy melyik kódrészletedet miért lesz felelős, és aszerint létrehozni neki packageket.

Mondok egy példát:

A teszt nevű projectem futtatni fog egy webszervert, aminek lesz egy endpoint-ja, (http://localhost:8081/sendMessage), ami küld egy automatikus üzenetet egy Discord szerver csatornájára, azzal a tartalommal, hogy “Chris 5 perc múlva jön játszani”.

Ha belegondolok, hogyan fogom megírni a kódot, egyből eszembe jut, hogy lesz egy main package, ami azért lesz felelős, hogy elinduljon a programunk.

Lesz egy server package, ami azért lesz felelős, hogy elérhető legyen a megálmodott endpoint, amin tudunk a szerverrel kommunikálni.

Végül pedig lesz egy discord package, amiben olyan Go kódot írok, ami képes kommunikálni a Discord szerverrel, és ez fogja elküldeni magát az üzenetet.

go packagek


go packagek

A go.mod fájl automatikusan létrejön amikor létrehozom a projectet. A go.sum fájl automatikusan létrejön, amikor a go get ... paranccsal elkezdesz különböző külső dependency-ket használni.

mkdir test # létrehozom a teszt projectet
cd test
go mod init github.com/SanFranciscobolJottem/test # létrehozom az elképzelt modult

go packagek

A cmd/[project_nev] mappa fogja tárolni a main.go és a config.go fáljlaimat, mind a kettőnek a tetején ott lesz a package main, így teljesen mindegy, hogy a fájlok neve micsoda. A Go fordító nem a fájlok nevére kíváncsi, hanem hogy legfelelül milyen package-et definiálsz az első sorban.

go packagek

Ezután pedig minden olyan kód, ami nem a program futtatásáért felelős, átkerül egy segéd package-be. A pkg mappa fogja tárolni az összes segéd package-t, amiben package megkapja a saját almappáját.

Végül pedig az almappákba bármennyi újabb .go fájlt betehetsz, és nem számít hogyan nevezed el őket. Ami számít, hogy a discord mappába tett Go fájlok mind kitegyék az első sorba a package discord jelölést. Ugyanígy a server mappába helyezett fájlok első sorában mind ott legyen a package server.

Innentől kezdve, a main.go használhatja a többi package függvényeit. Pontosabban, csak azokat, ahol a függvény nevének első betűje nagybetűvel van írva. A nagy betűvel kezdődő függvények ugyanis exportált függvények. Hasonlatosan a Java-hoz, ahol a public függvényeket lehetett package-n kívülről meghívni. A Go-ban nincs ilyen kulcsszó, hogy public, ehelyett a függyvény első karaktere határozza meg az elérhetőséget.

Ha most a main.go vagy a config.go fájlokban szeretnél meghívni függvényeket egy segéd package-ből, akkor azt így importálnád:

import [modulunk_neve] / pkg / [package_neve_ami_megegyezik_a_konyvtar_nevevel]

tehát:

import "github.com/SanFranciscobolJottem/test/pkg/server"

go packagek

Kattints a fenti képre, hogy lásd nagyban, és figyeld meg az összefüggéseket.

  • A config.go fájlban található printStart() függvénynek nem kell nagybetűvel kezdődni ahhoz, hogy a main.go hozzáférjen, mert mind a kettő kijelentette az első soraikban, hogy a main package-hez tartoznak.
  • A main() meg tudja hívni a server.Run() függvényt, mert annak a neve nagybetűvel kezdődik.
  • A discord package doStuff() függvényét nem tudja meghívni sem a main package, sem a server package, mert az kis betűvel kezdődik.

GitHub project

Összetettünk egy teszt projectet és megosztottuk GitHub-on, nyugodtan klónozzátok le, és próbáljátok ki!