Tot ce trebuie să știți despre pachete în Go

Inițializarea pachetelor

Când rulăm un program Go, compilatorul Go urmează o anumită ordine de execuție a pachetelor, a fișierelor dintr-un pachet și a declarațiilor variabilelor din acele fișiere.

Scopul pachetului

Un domeniu este o regiune dintr-un bloc de cod în care o variabilă definită este accesibilă. Domeniul de cuprindere al unui pachet este o regiune dintr-un pachet în care o variabilă declarată este accesibilă din interiorul unui pachet (în toate fișierele din pachet). Această regiune este cel mai de sus bloc din orice fișier din pachet.

Aruncă o privire la comanda go run. De data aceasta, în loc să executăm un singur fișier, avem un model glob pentru a include toate fișierele din interiorul pachetului app pentru a fi executate.

Go este suficient de inteligent pentru a-și da seama de un punct de intrare al aplicației, care este entry.go, deoarece are funcția main. De asemenea, putem utiliza o comandă ca cea de mai jos (ordinea numelor de fișiere nu contează).

go run src/app/version.go src/app/entry.go

💡 Puteți utiliza și comanda go run app care face același lucru și aceasta este o abordare mai bună pentru a executa un pachet. Comanda go install sau go build necesită un nume de pachet, care include toate fișierele din interiorul unui pachet, astfel încât nu trebuie să le specificăm ca mai sus.

Întorcându-ne la problema noastră principală, putem utiliza variabila version declarată în fișierul version.go de oriunde din pachet, chiar dacă nu este exportată (ca Version), deoarece este declarată în domeniul de aplicare al pachetului.

Dacă variabila version ar fi fost declarată în interiorul unei funcții, nu s-ar fi aflat în domeniul pachetului și programul de mai sus nu ar fi reușit să se compileze.

Nu aveți voie să declarați din nou o variabilă globală cu același nume în același pachet. Prin urmare, odată ce version variabila este declarată, ea nu poate fi redeclarată în domeniul de aplicare al pachetului. Dar sunteți liber să o redeclarați în altă parte.

Inițializarea variabilelor

Când o variabilă adepinde de o altă variabilă b, btrebuie definită în prealabil, altfel programul nu se va compila. Go respectă această regulă în interiorul funcțiilor.

Dar atunci când aceste variabile sunt definite în domeniul pachetului, ele sunt declarate în ciclurile de inițializare. Să ne uităm la exemplul simplu de mai jos.

În exemplul de mai sus, prima c este declarată pentru că valoarea sa este deja declarată. În ciclul de inițializare ulterior, b este declarat, deoarece depinde de c și valoarea lui c este deja declarată. În ciclul final de inițializare, a este declarat și atribuit la valoarea lui b. Go poate gestiona cicluri de inițializare complexe, cum ar fi cele de mai jos.

În exemplul de mai sus, mai întâi va fi declarat c, apoi b, deoarece valoarea sa depinde de c și, în final, a, deoarece valoarea sa depinde de b. Ar trebui să evitați orice buclă de inițializare ca cea de mai jos, unde inițializarea intră într-o buclă recursivă.

Un alt exemplu de domeniu de aplicare a pachetului ar fi, având o funcție f într-un fișier separat care face referire la variabila c din fișierul principal.

Funcția Init

Ca funcția main, init funcția init este apelată de Go atunci când un pachet este inițializat. Ea nu acceptă niciun argument și nu returnează nicio valoare.

Funcțiainiteste declarată implicit de Go, prin urmare nu o puteți referi de nicăieri (sau apela cainit()). Puteți avea mai multe funcțiiinitîntr-un fișier sau într-un pachet. Ordinea de execuție a funcțieiinitîntr-un fișier va fi în funcție de ordinea apariției lor.

Puteți avea funcția init oriunde în pachet. Aceste funcții init sunt apelate în ordinea lexicală a numelui de fișier (ordine alfabetică).

După ce toate funcțiileinit sunt executate, este apelată funcția main. Prin urmare, principala sarcină a funcției init este de a inițializa variabilele globale care nu pot fi inițializate în contextul global. De exemplu, inițializarea unui array.

Din moment ce sintaxa for nu este valabilă în cadrul pachetului, putem inițializa array-ul integers de dimensiune 10 folosind bucla for în interiorul funcției init.

Aliasul pachetului

Când importați un pachet, Go creează o variabilă folosind declarația pachetului respectiv. Dacă importați mai multe pachete cu același nume, acest lucru va duce la un conflict.

// greet/parent.go
package greetvar Message = "Hey there. I am parent."// greet/greet/child.go
package greetvar Message = "Hey there. I am child."

În consecință, folosim alias de pachet. Precizăm un nume de variabilă între cuvântul cheie import și numele pachetului, care devine noua variabilă pentru a face referire la pachet.

În exemplul de mai sus, pachetul greet/greet este acum referit prin variabila child. Dacă observați, am aliasat pachetul greet cu un semn de subliniere.

Semnul de subliniere este un caracter special în Go care acționează ca un container null. Deoarece importăm pachetul greet, dar nu îl folosim, compilatorul Go se va plânge de acest lucru. Pentru a evita acest lucru, stocăm referința acelui pachet în _, iar compilatorul Go o va ignora pur și simplu.

Aliind un pachet cu un underscore care pare să nu facă nimic este destul de util uneori, atunci când doriți să inițializați un pachet, dar nu îl utilizați.

// 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()")
}

Principalul lucru de reținut este că, un pachet importat este inițializat o singură dată pentru fiecare pachet. Prin urmare, dacă aveți mai multe declarații de import într-un pachet, un pachet importat va fi inițializat o singură dată pe durata de viață a execuției pachetului principal.

.