A Go modul, a saját tengerpartod
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.
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.
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
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.
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"
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 amain.go
hozzáférjen, mert mind a kettő kijelentette az első soraikban, hogy amain
package-hez tartoznak. - A
main()
meg tudja hívni aserver.Run()
függvényt, mert annak a neve nagybetűvel kezdődik. - A
discord
packagedoStuff()
függvényét nem tudja meghívni sem amain
package, sem aserver
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!