Deklarációk segítségével azonosítókat vezetünk be, melyekre később kényelmesen hivatkozhatunk. Nevet köthetünk konstanshoz, változóhoz, függvényhez és típushoz.
A csomag neve azonosító, de a package csomagnév
nem deklaráció.
A Go programban minden azonosítót, melyet használunk, deklarálni kell. Ugyanazt az azonosítót nem deklarálhatjuk egy blokkon belül kétszer, valamint nem deklarálhatjuk ugyanazt az azonosítót a fájl- és a csomagblokkban is.
Ha egy azonosítót, melyet egy külső blokkban deklaráltunk, újra deklarálunk a blokk egy belső blokkjában, akkor a belső deklaráció hatásköre elfedi a külső deklarációt.
Változót a var
kulcsszóval vezethetünk be var név típus
formában.
Kezdeti érték adható a változónak egyenlőségjel után (var x int = 42
). Kezdeti érték híján a változó értéke az alapérték lesz. Kezdeti érték megadása esetén a típus el is hagyható, ekkor a fordító kikövetkezteti a típust a jobboldali kifejezésből. Ennek szabályait ld. az Értékadás szakaszban.
Lehetőségünk van több változót deklarálni a var
egyszeri kiírásával, így:
Konstansokat a változókhoz hasonlóan, de a const
kulcsszó után deklarálhatunk, és mindig meg kell adnunk az értéküket. Ha egy konstans deklarációból elhagyjuk a típust és az értéke nemtípusos konstanst jelöl, nemtípusos konstanst kapunk (ld. Konstansok és Konstans kifejezés).
Speciális lehetőségként egy zárójeles const
szakaszon belül az első kivételével elhagyhatjuk az értékeket: ennek hatására az összes konstanst az első értékét kapja. Ezt együtt használva az iota
konstanssal hatékonyan tudunk egymást követő értékeket generálni.
A Go nyelvben a függvénydeklaráció a func
kulcsszó segítségével történik. A deklaráció során a func
kulcsszó után megadjuk a függvény nevét, majd zárójelben a paramétereket nevük és típusuk segítségével, végül zárójelben a visszatérési értékek típusait. A függvényblokk elejét és végét kapcsos zárójelek jelzik a C típusú nyelvekhez hasonlóan.
Az azonos típusú paraméterek rövidíthetőek. Ha minden paraméter típusa azonos, akkor a típust csak egyszer kell kiírnunk, a változóneveket, pedig vesszővel választjuk el. Ezek alapján
func add(x int, y int){}
megegyezik
func add(x,y int){}
függvénnyel
Amint láthattuk több visszatérési értéke is lehet a függvénynek. A paraméterekhez hasonlóan a visszatérési értékek is elnevezhetőek és rövidíthetőek. Ezek a nevek felhasználhatóak a függvényblokkon belül.
A függvénydeklaráció végén jelölhetünk változó számú paramétereket is a ...
jelöléssel. Ez lehet nulla vagy több paraméter is, amely a megadott típusú változókból álló slice-ként adódik át.
Van szimultán értékadás, ekkor a bal és jobboldalon álló elemek számának (és típusának) meg kell egyeznie. Ha nem akarjuk felhasználni valamelyik értéket a jobb oldalról, akkor a bal oldalon a megfelelő helyre írhatunk _
üres azonosítót, így az ehhez tartozó érték elveszik.
A szimultán értékadás segítségével nyerhetjük ki többszörös visszatérési értékű függvények visszatérési értékét, pl.:
Szimultán értékadással akár két változó értékét is felcserélhetjük: x, y = y, x
utasítás legális és az elvárásainknak megfelelően működik.
Függvény törzsén belül a var
kulcsszó nélkül, rövidebb formában tudunk bevezetni változót a :=
operátorral. Ekkor a típus kikövetkeztetésre kerül a jobb oldali értékből.
Ebben az esetben is használhatjuk a szimultán értékadás lehetőségét. Ha legalább egy új azonosító van a bal oldalon, akkor használhatunk :=
-t. Pl.:
Ha op
egy operátor, akkor x op= y
megegyezik x = x op y
-nal (de x
csak egyszer értékelődik ki). Ebben az esetben mindkét oldalon pontosan egy kifejezés állhat.
A C++-szal ellentétben a Go nyelvben a megszokott ++ és -- operátorok nem kifejezések, hanem utasítások, ezért csak önállóan állhatnak.
A készítőknek választaniuk kellett a prefix és a postfix forma (++x ill. x++) közül. Választásuk az utóbbira esett, hiszen a C++-nak is a nevében ez van, az előbbi változat csak a boost könyvtár megjelenése óta terjedt el, hatékonysági okokból.
Az if
kulcsszóval; nincs többágú elágazás, csak egymásba ágyazott if
kifejezések.
A kezdőutasítás egy egyszerű utasítás lehet, ez elhagyható. A { }
zárójelek kötelezőek, a feltételnek logikai kifejezésnek kell lennie.
Kétféle switch utasítás létezik a nyelvben. Az első egy kifejezés értéke alapján hajtja végre valamelyik ágat, a második egy érték típusa alapján. A vezérlés nem megy tovább a következő ágra, mint C++-ban, kivéve, ha az ág utolsó utasítása a fallthrough
(ez az utasítás nem használható típus alapú switchben).
switch
A kezdő utasítás szabadon elhagyható. Ha a logikai kifejezést elhagyjuk, az értéke alapértelmezett módon true
lesz, így a következő elágazás is helyes:
A default
ág nem kötelező, illetve nem szükséges, hogy a switch
végén legyen. Egyes ágakhoz több értéket is írhatunk, az első illeszkedő értékhez tartozó ág fut le.
Az értékek tetszőlegesek lehetnek, kiértékelésük balról jobbra és fentről lefelé történik az első egyezésig - ezután a megfelelő ág lefut és a többi értéket a program nem értékeli ki (a 2. példában például ha x < y
, akkor sem f2()
, sem f3()
nem kerül kiértékelésre).
switch
Ezt akkor használhatjuk, ha a kifejezés valamilyen interface típusú, és a dinamikus típusától függően akarunk más-más utasításokat végrehajtani.
A kezdőutasítás itt is elhagyható. Az azonosító és a :=
szintén opcionális: ha van ilyen, akkor a név minden case-ágban használható és az ágnak megfelelő típusú lesz.
Megengedett továbbá a nil
ág is: ez akkor fut le, ha a vizsgált kifejezés egy nil
interface érték.
A Go-ban egyetlen kulcsszó van a különböző ciklusokra, a for
.
Az első fajta ciklus a szokásos while-nak felel meg. Ez egy egyszerű elől tesztelő ciklus, ami addig fut, amíg a ciklusfeltétel teljesül.
A második fajta ciklus a C++-os for ciklus. Itt (ahogy a C++-ban is) bármelyik rész lehet üres utasítás is.
A harmadik egy foreach-jellegű ciklus a range
kulcsszóval. Ezzel tömbökön, szeleteken, map-eken, stringeken és csatornákon iterálhatunk végig.
A csatornák kivételével két értéket ad vissza a range
minden iterációnál: az aktuális elem indexét és az aktuális elem értékét. Utóbbit (fent value
) elhagyhatjuk (az index eldobására a _
üres azonosítót használhatjuk). Csatornák esetében egy értéket kapunk, ekkor addig fogad elemeket a csatornán, amíg az nincs bezárva és nem üres.
Negyedik lehetőségünk a végtelen ciklus:
Break
és continue
A break
utasítás a bennfoglaló legbelső for
, switch
vagy select
utasítás megszakítására szolgál.
A continue
utasítás a legbelső bennfoglaló ciklust (for
utasítást) új iteráció megkezdésére kényszeríti.
A ciklusok, illetve switch
és select
utasítások elláthatók címkével, pl.:
Ekkor az ilyen ciklusban, switch
-ben vagy select
-ben hívható a break
, ill. continue
utasítás címkézett változata, ami ekkor az adott címkével ellátott vezérlési szerkezetre vonatkozik. Így például egymásba ágyazott ciklusok vagy elágazás utasítások esetén nem csak a legbelsőt tudjuk vezérelni. Pl.:
Valójában tetszőleges utasítás ellátható címkével, és a goto címke
utasítással ugorhatunk a címkével megjelölt utasításra. Nem ugorhatunk azonban át (vagy be) a goto
utasítást tartalmazó blokktól különböző blokkba, illetve az ugrás hatására nem kerülhetünk olyan változó hatáskörébe, amelynek a hatásköre nem foglalja magában az ugró utasítást. Példák:
go
utasítás
A go
utasítás a megadott függvény- vagy metódushívást független, konkurens végrehajtási szálon (de azonos memória-címtérben) indítja el és azonnal visszatér. A go
utasítással elindított szubrutinokat gorutinoknak nevezzük. Pl.:
A gorutinban indított függvények (metódusok) esetleges visszatérési értéke a futás végén eldobásra kerül. A kommunikációt csatornákkal (chan
) biztosíthatjuk a különböző gorutinok, ill. a főprogram között.
A select
utasítás olyan esetekben használható, amikor többféle, csatornán történő kommunikáció közül kell választani. Szintaxisa hasonló a switch
-éhez.
Amikor a vezérlés a select
utasításhoz ér, fentről lefele kiértékeli az összes ágat. Ezután a következők történhetnek:
default
ág, az végrehajtódik, ha nincs, a folyamat blokkolódikA blokk deklarációk és utasítások sorozata, kapcsos zárójelek között. A nyelv az azonosítók hatókörét a blokkok alapján határozza meg. A blokkok egymásba ágyazhatók.
Mivel a fordításkor a fordító pótolja a ki nem írt pontosvesszőket a sorok végén, a blokkok kezdő kapcsos zárójelét egy sorba kell írni azzal a kulcsszóval, amihez tartozik. Például ez helyes:
Ez viszont helytelen:
Az explicit blokkok mellett automatikusan létrejönnek implicit blokkok is:
if
, for
és switch
egy saját implicit blokkban vanswitch
és select
utasításokban külön blokkban vanBlokkok végtelen mélységig egymásba ágyazhatók. Alapvetően befolyásolják a változók hatáskörét.