Pakett inicializálás
Mikor egy Go programot futtatunk, a Go fordító egy bizonyos végrehajtási sorrendet követ a csomagok, a csomagban lévő fájlok és az ezekben lévő változó deklarációk esetében.
Pakett hatókör
A hatókör egy olyan régió a kódblokkban, ahol egy definiált változó elérhető. A csomag hatókör egy olyan terület egy csomagon belül, ahol egy deklarált változó elérhető a csomagon belül (a csomag összes fájljában). Ez a régió a csomag bármely fájljának legfelső blokkja.
Nézd meg a go run
parancsot. Ezúttal egy fájl végrehajtása helyett egy glob mintát használunk, hogy a app
csomagon belüli összes fájlt bevonjuk a végrehajtáshoz.
Go elég okos ahhoz, hogy kitalálja az alkalmazás belépési pontját, ami a entry.go
, mivel rendelkezik main
funkcióval. Használhatunk egy olyan parancsot is, mint az alábbi (a fájlnevek sorrendje nem számít).
go run src/app/version.go src/app/entry.go
💡 Használhatjuk a
go run app
parancsot is, amely ugyanezt teszi, és ez egy jobb megközelítés a csomag végrehajtásához. Ago install
vagygo build
parancs egy csomagnevet igényel, amely tartalmazza a csomagon belüli összes fájlt, így nem kell megadnunk őket, mint fentebb.
A fő problémánkhoz visszatérve, a version.go
fájlban deklarált version
változót bárhol használhatjuk a csomagban, még akkor is, ha nincs exportálva (mint Version
), mert a csomag hatókörében van deklarálva.
Ha a version
változót egy függvényen belül deklaráltuk volna, akkor nem lett volna a csomag hatókörében, és a fenti program nem tudott volna lefordítani.
Egy globális változót nem szabad újra deklarálni ugyanazzal a névvel ugyanabban a csomagban. Ezért a version
egyszer deklarált változót nem lehet újra deklarálni a csomag hatókörében. Máshol azonban szabadon újra deklarálható.
A csomagban bárhol lehet init
függvényed. Ezek a init
függvények lexikális fájlnévsorrendben (ábécésorrendben) kerülnek meghívásra.
Az összes init
függvény végrehajtása után a main
függvény kerül meghívásra. A init
függvény fő feladata tehát a globális változók inicializálása, amelyek nem inicializálhatók a globális kontextusban. Például egy tömb inicializálása.
Mivel a for
szintaxis nem érvényes a csomag hatókörében, a init
függvényen belüli for
ciklus segítségével inicializálhatjuk a integers
méretű 10
tömböt.
Package alias
Amikor importálunk egy csomagot, Go hozzunk létre egy változót a csomag csomag deklarációját használva. Ha több azonos nevű csomagot importálunk, ez konfliktushoz vezet.
// greet/parent.go
package greetvar Message = "Hey there. I am parent."// greet/greet/child.go
package greetvar Message = "Hey there. I am child."
Ezért használjuk a package alias-t. A import
kulcsszó és a csomag neve között megadunk egy változó nevét, amely a csomagra való hivatkozás új változója lesz.
A fenti példában a csomagra most a child
változóval hivatkozunk. Ha észrevetted, a greet
csomagot egy aláhúzással aliasosítottuk.
Az aláhúzás egy speciális karakter a Go-ban, amely null
tárolóként működik. Mivel importáljuk a greet
csomagot, de nem használjuk, a Go fordító panaszkodni fog emiatt. Hogy ezt elkerüljük, a csomag hivatkozását a _
-be tároljuk, és a Go fordító egyszerűen figyelmen kívül hagyja.
A csomagot egy aláhúzással, ami látszólag semmit sem csinál, néha nagyon hasznos, amikor inicializálni akarunk egy csomagot, de nem használjuk.
// greet/parent.go
package greetimport "fmt"var Message = "Hey there. I am parent."func init() {
fmt.Println("greet/parent.go ==> init()")
}// greet/greet/child.go
package greetimport "fmt"var Message = "Hey there. I am child."func init() {
fmt.Println("greet/greet/child.go ==> init()")
}
A legfontosabb, hogy egy importált csomagot csomagonként csak egyszer inicializálunk. Ezért ha több import utasítás van egy csomagban, akkor egy importált csomag csak egyszer lesz inicializálva a főcsomag futtatásának élettartama alatt.