Paketinitialisering
När vi kör ett Go-program följer Go-kompilatorn en viss exekveringsordning för paket, filer i ett paket och variabeldeklarationer i dessa filer.
Paketomfång
Ett omfång är ett område i ett kodblock där en definierad variabel är tillgänglig. Ett paketomfång är ett område inom ett paket där en deklarerad variabel är tillgänglig från ett paket (över alla filer i paketet). Detta område är det översta blocket i alla filer i paketet.
Ta en titt på kommandot go run
. Den här gången har vi istället för att exekvera en fil ett globmönster för att inkludera alla filer i app
-paketet för exekvering.
Go är smart nog att räkna ut en ingångspunkt för programmet som är entry.go
eftersom den har main
-funktionen. Vi kan också använda ett kommando som nedan (filnamnsordningen spelar ingen roll).
go run src/app/version.go src/app/entry.go
💡 Du kan också använda kommandot
go run app
som gör samma sak och detta är en bättre metod för att exekvera ett paket. Kommandogo install
ellergo build
kräver ett paketnamn, vilket inkluderar alla filer i ett paket, så vi behöver inte specificera dem som ovan.
Vid återgång till vår huvudfråga kan vi använda variabeln version
som deklarerats i filen version.go
var som helst i paketet, även om den inte exporteras (som Version
), eftersom den deklareras i paketets omfattning.
Om version
-variabeln hade deklarerats i en funktion hade den inte funnits i paketomfånget och ovanstående program hade inte kunnat kompileras.
Det är inte tillåtet att omdeklarera en global variabel med samma namn i samma paket. När version
variabeln väl har deklarerats kan den därför inte omdeklareras i paketets omfattning. Men det står dig fritt att återdeklarera någon annanstans.
Variabelns initialisering
När en variabel a
är beroende av en annan variabel b
ska b
definieras i förväg, annars kan programmet inte kompileras. Go följer denna regel inuti funktioner.
Men när dessa variabler definieras i paketomfånget deklareras de i initialiseringscykler. Låt oss ta en titt på det enkla exemplet nedan:
I exemplet ovan deklareras först c
eftersom dess värde redan är deklarerat. I den senare initialiseringscykeln deklareras b
eftersom den är beroende av c
och värdet av c
redan är deklarerat. I den sista initialiseringscykeln deklareras a
och tilldelas värdet för b
. Go kan hantera komplexa initialiseringscykler som nedan:
I exemplet ovan kommer först c
att deklareras och sedan b
eftersom dess värde är beroende av c
och till sist a
eftersom dess värde är beroende av b
. Du bör undvika en initialiseringsslinga som nedan där initialiseringen hamnar i en rekursiv slinga.
Ett annat exempel på paketets räckvidd är att ha en funktion f
i en separat fil som refererar till variabeln c
från huvudfilen.
Init-funktion
Likt main
funktion, init
funktionen anropas av Go när ett paket initieras. Den tar inte emot några argument och returnerar inget värde.
Funktionen init
deklareras implicit av Go, därför kan du inte referera till den från någonstans (eller anropa den som init()
). Du kan ha flera init
-funktioner i en fil eller ett paket. Ordningen för utförandet av init
-funktioner i en fil kommer att vara enligt den ordning i vilken de dyker upp.
Du kan ha init
-funktionen var som helst i paketet. Dessa init
-funktioner anropas i lexikalisk filnamnsordning (alfabetisk ordning).
När allainit
-funktioner har utförts anropas main
-funktionen. Därför är init
-funktionens huvuduppgift att initialisera globala variabler som inte kan initialiseras i den globala kontexten. Exempelvis initialisering av en array.
Då for
-syntaxen inte är giltig i paketets räckvidd kan vi initialisera arrayen integers
med storleken 10
med hjälp av for
-slinga inuti init
-funktionen.
Paketalias
När du importerar ett paket skapar Go en variabel med hjälp av paketdeklarationen för paketet. Om du importerar flera paket med samma namn leder detta till en konflikt.
// greet/parent.go
package greetvar Message = "Hey there. I am parent."// greet/greet/child.go
package greetvar Message = "Hey there. I am child."
Därför använder vi package alias. Vi anger ett variabelnamn mellan nyckelordet import
och paketnamnet som blir den nya variabeln för att referera till paketet.
Det viktigaste att komma ihåg är att ett importerat paket initialiseras endast en gång per paket. Om du har flera importmeddelanden i ett paket kommer därför ett importerat paket att initialiseras endast en gång under huvudpaketets livstid.