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.
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.
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.
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.
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.