Parancsok

Két go parancsot már ismerünk, a go build és a go run parancsokat. Most ismerkedjünk meg még párral.


állatorvos - pexels.com - Mikhail Nilov fényképe

Go vet

A go vet-ről nekem mindig egy állatorvos jut eszembe (vet -> állatorvos), aki megvizsgálja a forráskódunk épségét.

Nézd meg az alábbi Go kódot, és gondold át mi lehet a hiba benne:

package main

import "fmt"

func main() {
	age := 3

	fmt.Printf("Hello Gyula, a korod: %s", age)
}
Ha eleget gondolkodtál, kattints ide a válaszért


A hiba a %s, ami a string-ek kiíratására van. Mivel az age egy szám érték, ezért a %v-vel kellene kiíratni.

Mindentől függetlenül a kód lefut, csak ehelyett:

Hello Gyula, a korod: 3

ezt kapod:

Hello Gyula, a korod: %!s(int=3)


Ez egy szemantikai hiba, vagyis a kód tartalma hibás. Azáltal, hogy van egy ilyen hiba a kódodban, megváltozik a viselkedése, hiszen mást ír ki, mint amit várunk tőle. A go vet, az ilyen, és ehhez hasonló szemantikai hibákat keresi, és futtatásakor szól, ha talált hibát a kódodban. Például a fent említett kód esetén ha lefuttatod, akkor az alábbi szöveggel tér vissza:

go vet ./hellogyula
# command-line-arguments
.\hellogyula.go:8:2: Printf format %s has arg age of wrong type int

Ebben megmondja, hogy 1: melyik fájlban talált hibát 2: hányadik sorban 3: hányadik karakternél 4: mi volt a hiba

A vet tehát egy olyan parancs, amit azelőtt érdemes lefuttatnunk, mielőtt kiadunk a kezünkből egy új változatot a futtatható fájlból. Éppen ezért gyakran része a Go projectet támogató Makefile-nak.


autószerelő - pexels.com - Malte Luk fényképe

Go fmt

A go fmt-ről nekem valamiért mindig az az autószerelő ismerősöm jut eszembe, aki azelőtt nekiáll megszerelni a kocsit, hogy elmondanám mi a problémám vele.

A go fmt egy beépített formatter, magyarán nem szemantikai, hanem szintaktikai hibákat keres, és ki is javítja azokat. Szintaktikai hiba lehet például, ha nem teszel ki egy white space-t két karakter között.

package main

import "fmt"

func main() {
	age :=3

	fmt.Printf("Hello Gyula, a korod: %s",age)
}

Ebben a kódban láthatod, hogy az egyenlőségjel, és a 3 között nincsen white space. Ugyanez igaz a vessző és az age esetére. Ez így csúnya, nehezebben olvasható, mintha lenne ott. Ha lefuttatod az alábbi parancsot, akkor a space-k automatikusan be lesznek illesztve:

go fmt ./hellogyula

Egyébként ha megpróbálod bemásolni a fentebbi hibás kódot Visual Studio Code-ba, és elmented a fájlt, a space-k automatikusan ki lesznek javítva. Ez azért van, mert a VSCode automatikusan formázza a kódodat mentéskor.

Az fmt tehát ismét csak egy olyan parancs, amit azelőtt érdemes lefuttatnunk, mielőtt kiadunk a kezünkből egy új változatot a futtatható fájlból. Éppen ezért ez is gyakran része a Go projectet támogató Makefile-nak.


Homokvár a parton - pexels.com - Gerardo Ramones fényképe

Go mod

Képzelj el egy tengerpartot. Ez a tengerpart a helye az összes Go forráskódodnak, így azt írsz a homokba, vagy építesz homokból, amit csak szeretnél.

A te saját tengerpartod a $GOPATH alatt van, vagyis a felhasználód HOME mappáján belül, a $HOME/go-ban (ha nem változtattad meg az alapvető beállítást a Go telepítésnél).

Amikor Go-ban programozunk, különböző .go kiterjesztésű fájlokat hozunk létre, és őket különböző package-ekben definiáljuk a fájlok tetején. Így jelöljük a forráskódban, hogy melyik fájl logikailag hova tartozik. Addig, ameddig ezek a fájlok a $GOPATH területén belül vannak, addig könnyen látják egymást, és egyik package-ből tudsz hivatkozni egy másik package-re. Minden egyes létrehozott package olyan, mint egy homokvár, amit te építettél a tengerparton. Ha a homokvárak között ásol egy árkot, akkor összekötheted őket, tehát a package-k látják egymást, tudnak egymással interaktálni.

go mod init

Amikor saját modult hozol létre, akkor felhúzhatsz egy falat egy homokvár (vagy akár egy csapat homokvár) köré, és azt mondhatod: Mostantól minden, ami a falon belül van, az logikailag egybe tartozik, ez együtt egy module. Innentől kezdve az sem fontos, hogy a tengerparton legyen, bárki elszállíthatja ezt a module-t ahova csak szeretné, a lényeg, hogy minden, ami a falon belül van, az együtt létezik, összetartozik.

Amikor tehát létrehozol egy Go module-t a $HOME/go mappán kívül, akkor a könyvtáradban kijelentheted, hogy mostantól fogva ez egy elkerített részleg, egy logikailag egybe tartozó összessége az itt található package-eknek.

mkdir projectA
cd projectA
go mod init github.com/[GitHub_Felhasznalo_neved]/projectA

A fenti parancsok mutatják egy könyvtár létrehozását, majd a könyvtárban egy go module létrehozását. A go mod init után bármilyen értéket átadhatnál, lehetne az egyetlen szó is akár. (go mod init jutka)

Az oka annak, hogy úgy definiáljuk ahogy a példa mutatja (go mod init github.com/[GitHub_Felhasznalo_neved]/projectA), az az, hogy elterjedt szokás a GitHub repository linkjét adni (https nélkül) a module nevének, hogy egyedi legyen a neve a module-nak (A GitHub profilod neve egyedül a tiéd a világon a GitHubon), és ha esetleg később nyílt forráskódúvá teszed a module-t, akkor bárki könnyen elérje, és tudja importálni azt.

Ez a parancs úgy hozza létre a modul-t, hogy létrehoz egy go.mod fájlt az adott könyvtáron belül, ami egy jel a Go-nak. Ez a jel megérteti vele, hogy MINDEN ami ebben a könyvtárban van (akár alkönyvtárakban), az logikailag egybe tartozik, és ezért a package-ek a könyvtáron belül fel fogják ismerni egymást, akkor is, ha az egész module a $HOME/go mappán kívül él.


kutya hoz valamit - pexels.com - Aldo Carillo fényképe

Go get

A Go-ban az az egyik legjobb dolog, hogy nagyon könnyű újrahasznosítani kódot. Például írhatunk egy module-t, amit feltöltünk github-ra, publikussá tesszük a repositoryt, amiben a Go module található. Ezek után az emberek beimportálhatják a saját Go kódjukba, az import sorban. Ahhoz, hogy valaki lokálisan rendelkezzenek a már megírt külső modullal, egyetlen dolgot kell tennie: le kell húznia a module-t az internetről.

A go get egy olyan parancs, amivel megkéred a Go-t, hogy húzzon le a gépedre egy külső (általában valaki más által megírt) Go module-t. A hely, ahova a module letöltődik, attól függ, hogy te magad egy olyan könyvtárban vagy (amikor beírod ezt a parancsot), ami önmagában egy általad fejlesztett Go module könyvtára, vagy pedig egy olyan könyvtárban vagy a terminálon, ahol nincs jelen saját Go module.

A saját Go module-od esetében a go get letölti dependencyt a saját go module-odhoz. Ezt úgy éri el, hogy létrejön egy új sor a go.mod fájlodban, és amikor legközelebb lefuttatod a module-t, látni fogod, hogy tölt külső dependency-ket.

Ha nem egy Go module mappájában vagy, akkor a go get letölti dependencyt a $HOME/go könyvtárba, hogy globálisan elérhető legyen a gépeden.


Próbáld ki

Futtasd le az alábbi parancsot a terminálodban egy olyan mappában, ahol nincsen go.mod fájl:

go get -u golang.org/x/lint/golint

Ez megkéri a Go-t, hogy töltse le ezt a module-t, amit egy csapat megírt és feltöltött az internetre. A -u paraméter arra kéri a go get-et, hogy ha már le van töltve a gépre, akkor töltse le (frissítse) újra.

Amikor Windows-on futtatom ezt a parancsot, egy olyan mappában, ahol nincsen go.mod fájl, akkor a C:\Users\[felhasznaloi_nev]\go\pkg\mod\golang.org\x mappába tölti le ezt a module-t (dependency-t).

Ha viszont létrehozok egy module-t, és ott írom be ugyanezt a parancsot, akkor a go.mod fájlhoz ad hozzá egy új bejegyzést.

A golint egy olyan dependency, amit ma már nem használnak, csak a module példa kedvéért telepítettük. Ne használd igazi projectben!

mkdir teszt
cd teszt
go mod init teszt
go get golang.org/x/lint/golint

A go.mod fájl tartalma:

module teszt

go 1.16

require (
	golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
	golang.org/x/tools v0.1.2 // indirect
)


Go install

Azt mostanra tudjuk, hogy a go build összekészít nekünk egy futtatható binary fájlt.

A go install ugyanezt teszi, de az elkészült fájlt automatikusan a $GOPATH/bin mappába teszi. Ezenkívül az összes $GOPATH/pkg-ben található package-t cache-eli, és elérhetővé teszi a fordítónak.

Mivel az SFJ-s tutorialok zömében module-okat építünk, ezért ezt a parancsot nem nagyon fogjuk használni.

Go parancsok