A függvényeket a func
szó vezeti be. Ezt követi a függvény neve, majd zárójelek között a formális paraméterek (az egyes változók neve, illetve típusa ebben a sorrendben), majd végül a visszatérési érték típusa. Ha nincs visszatérési érték, akkor semmit nem kell írnunk.
Egyszerre több visszatérési érték is lehet, ekkor ezek típusát zárójelek között kell vesszővel elválasztva felsorolni, pl.:
A visszatérési érték(ek)nek adhatunk nevet is. Ekkor a függvény törzsében az adott nevet lokális változóként használhatjuk, és a futás végén (a return
utasítás végrehajtásakor) meglévő értéke lesz a visszatérési érték.
Mind a paraméterek, mind a visszatérési értékek listájából elhagyhatjuk a változóneveket, de mindkét listára igaz, hogy vagy az összes nevet elhagyjuk, vagy mindet ki kell írnunk. Ha egyes paramétereket nem szeretnénk használni, azok számára használhatjuk az üres azonosítót (_
).
return
utasítás használata
A return
utasítás befejezi egy függvény futását, és esetleg megadhatja a visszatérési értékeket is.
Visszatéréi értékkel nem rendelkező függvényben szereplő return
-nek tilos visszatérési érték(ek)et megadni. Ilyen függvényekben nem kötelező szerepeltetni a kulcsszót, ekkor a blokkja végén a függvény véget ér.
Kötelező viszont szerepeltetni a return
-t minden olyan függvény és metódus végén, amely rendelkezik visszatérési értékkel. Ez azt is jelenti, hogy ha egy egyszerű elágazás mindkét ágában szerepel, az nem helyes kód (mivel pl. goto
utasítással akár ki is ugorhatunk az elágazásból).
A visszatéréi értékek megadására három lehetőség van:
return
utasítás után, vesszővel elválasztva (pl. return 1, 12.3
).return
utasítást, és a megfelelő változók értékeit adja vissza a függvény.return
után állhat egy több visszatérési értékkel rendelkező függvény hívása is abban az esetben, ha a két függvény visszatérési értékei egymásnak rendre értékül adhatók.receiver
) paraméter
A func
szó és a függvény neve közé zárójelek közt egy újabb típus (illetve változó) neve is beékelődhet. Ekkor nevezzük a függvényt metódusnak. Az adott függvény a megfelelő típusú változó után pontot írva hívható meg, hasonlóan ahhoz, ahogy az objektumorientált nyelvekben szokás.
Példa:
A fogadó típus T
vagy *T
alakú kell, hogy legyen, ahol T
nem pointer és nem interface típusnév, és a metódussal azonos csomagban deklarálták (vagy előre definiált).
Ha a fogadó típusa *T
, akkor a paraméter egy pointer, és a referált értéket a metódus ennek megfelelően megváltoztathatja. ha a fogadó paraméter nem pointer típus, akkor a fogadó paraméter értékének változtatása nem hat a függvény törzsén kívül.
Egy típusra definiált metódusok neve mind különböző kell, hogy legyen, továbbá, ha a fogadó típus rekord (struct
), akkor a mezők nevével sem lehet ütközés.
A metódus típusa a hasonló szignatúrájú függvény típusa, de első paramétere a fogadó paraméter, ezt követi a többi paraméter. Pl.:
Azonban egy ilyen módon definiált függvény nem lesz a Point
típus metódusa.
Interface-eket metódusok segítségével valósíthatunk meg: ha egy típus megvalósítja egy interface összes metódusát, akkor megvalósítja az interface-t. Pl.:
A paraméterek alapértelmezetten érték szerint adódnak át, kivéve a szelet, map és csatorna típusú paramétereket (ezek referencia szerint kerülnek átadásra). Out és inout paraméterátadási mód megvalósítására ezen túl mutatókat használhatunk.
Speciális paramétertípus a ...T
. Ez azt jelöli, hogy az adott helyre változó számú, T
típusú paraméter kerülhet. Ez muszáj, hogy a paraméterlista utolsó eleme legyen. Például a klasszikus printf
deklarációja Go-ban:
A ...T
paraméter átadása []T
valójában típusként történik (pl. az előbbi Printf
törzsében a paramétereket az args[i]
indexeléssel érhetnénk el).
Megfelelő típusú szeletet is átadhatunk a ...T
paraméter számára, ekkor a szeletet eredményező kifejezés végére híváskor ...
-ot kell írni, pl.:
Túlterhelésre a Go nyelvben nincs lehetőség. Viszont hasonló hatást érhetünk el a fent említett ...
alkalmazásával.
Másik lehetőségünk a túlterhelés szimulálására az interface{}
típus használata. Mivel az üres interface-t minden típus megvalósítja, ezért ilyen típusú paraméterként majdnem bármilyen érték átadható, majd ez a típusalapú switch
konstrukció segítségével megfelelő dinamikus típusra alakítható.
Alprogramok rekurzív hívása a megszokottak szerint működik.
Minden Go fájl a package
kulcsszóval kezdődik, majd ezt egy csomagnév követi, mely egy azonosító. Ez mondja meg, hogy melyik csomaghoz tartozik. Egy csomag több fájlból is állhat, ám azon fájloknak egy könyvtárban kell lenniük.
A package rész után az import
rész jön, mely azt mondja meg, hogy mi mely csomagokat szeretnénk felhasználni.
Végül típusok és függvények sokasága jön. Azt, hogy melyik látszik kívülről, a név kezdőbetűje dönti el: a nagybetűvel kezdődőek látszanak kívülről, a többiek nem. (Nagybetű alatt a Unicode nagybetű osztályát értjük, tehát pl. az Űrhajó függvény látszik kívülről. Ezen a ponton viszont a távol-keleti nyelvek hátrányban vannak, mert ott nincs kis- ill. nagybetű.)
A csomagok tartalmazhatnak egy vagy több init()
függvényt. Ezek a csomag importálásakor futnak le, miután a csomag szintű változók értéket kaptak. Ha a csomag további csomagokat importál, ezek előbb ezek inicializálódnak. Ha több init()
függvény van, mindegyik lefut, de a sorrendjükre nincs megkötés.
Minden programban kell lennie egy main
csomagnak, benne egy main()
függvénnyel. A program belépési pontja ez a main.main()
függvény lesz.