3 lucruri care fac diferența

Go este o limbă specială. Este foarte răcoritoare în abordarea programării și principiile pe care le promovează. Ea ajută că unii dintre inventatorii de limbi străine au fost pionieri C timpurii. Sentimentul general al lui Go este secolul al XX-lea al secolului al XX-lea. 

În acest tutorial, veți afla despre trei dintre caracteristicile care fac Go unic: simplitatea sa, modelul de concurență prin intermediul gorutinei și mecanismul de manipulare a erorilor.

1. Simplitate

Multe limbi moderne de succes precum Scala și Rust sunt foarte bogate și oferă sisteme avansate de tip și sisteme de gestionare a memoriei. Aceste limbi au luat limbile de masă ale timpului lor, cum ar fi C ++, Java și C # și au adăugat sau îmbunătățit capabilitățile. Du-te a luat un alt traseu și a eliminat o mulțime de caracteristici și capabilități. 

Nu generice

Genericile sau șabloanele reprezintă o bază a multor limbi de programare. Ele adesea adaugă complexitate, iar mesajele de eroare asociate genericilor pot fi uneori obscure. Go designeri au decis să o săriți. 

Aceasta este, fără îndoială, cea mai controversată decizie de proiectare a Go. Personal, găsesc o mulțime de valoare în medicamentele generice și cred că se poate face în mod corespunzător (a se vedea C # pentru un exemplu excelent de medicamente generice realizate corect). Sperăm că generice vor fi incluse în Go în viitor. 

Fara exceptii

Manipularea erorilor de către Golang se bazează pe coduri de stare explicite. Pentru a separa starea de rezultatul real al unei funcții, Go acceptă mai multe valori returnate dintr-o funcție. Acest lucru este destul de neobișnuit. O voi acoperi cu mult mai multe detalii mai târziu, dar aici este un exemplu rapid:

(float64, eroare) if b == 0 return 0, errors.New (fmt.Sprintf ("Nu se poate împărți% f prin zero ", a)) returnați a / b, nil func principal () rezultat, err: = div (8, 4) err! = nil fmt.Println" + err.Error ()) altceva fmt.Println (rezultat) rezultat, err = div (5, 0) err! = nil fmt.Println ("Oh- oh, something iswrong. ()) altceva fmt.Println (rezultat) 2 Oh-oh, ceva nu este bine. Nu se poate împări 5.000000 la zero 

Executabil singular

Go nu are o bibliotecă de runtime separată. Acesta generează un singur executabil, pe care îl puteți implementa doar prin copiere (de exemplu, implementarea XCOPY). Acest lucru este la fel de simplu ca acesta devine. Nu trebuie să vă faceți griji în legătură cu dependențele sau nepotrivirile versiunii. Este, de asemenea, un bun avantaj pentru implementările pe bază de containere (Docker, Kubernetes și prieteni). Executivul standalone unic face pentru Dockerfiles foarte simplu.   

Nu există biblioteci dinamice

O.K. Acest lucru sa schimbat recent în Go 1.8. Acum puteți încărca de fapt biblioteci dinamice prin conecteaza pachet. Dar, din moment ce această capacitate nu a fost introdusă de pe urma, mă consider încă o extensie pentru situații speciale. Spiritul Go este încă un executabil static compilat. Este disponibil și numai pe Linux.

2. Gorutinele

Gorutinele sunt probabil cel mai atractiv aspect al Go din punct de vedere practic. Gorutine vă permit să valorificați puterea mașinilor multicore într-un mod foarte ușor de utilizat. Se bazează pe baze teoretice solide, iar sintaxa care o susține este foarte plăcută.

CSP

Fundamentul modelului de concurență al lui Go este procesele secvențiale de comunicare ale lui C. A. R. Hoare. Ideea este de a evita sincronizarea în memoria partajată între mai multe fire de execuție, care sunt predispuse la erori și care necesită forță de muncă. În schimb, comunicați prin canale care evită contestația.

Invocați o funcție ca o Gorutină

Orice funcție poate fi invocată ca o gorutină prin apelarea acesteia prin cuvântul cheie go. Luați în considerare mai întâi următorul program liniar. foo ()funcția de dormit timp de câteva secunde și imprimă câte secunde a dormit. În această versiune, fiecare apel la foo () blochează înainte de următorul apel.

(fmt "time") func f (d time.Duration) d * = 1000000000 time.Sleep (d) fmt.Println (d) func main () foo (3) foo (1) pentru foo (4) 

Ieșirea urmează ordinului de apeluri din cod:

3s 2s 1s 4s

Acum, o să fac o mică schimbare și să adaug cuvântul cheie "du-te" înainte de primele trei invocări:

pachetul principal de import ("fmt" // "erori" "time") func foo (d time.Duration) d * = 1000000000 time.Sleep (d) fmt.Println (d) 3) du-te foo (2) go foo (1) foo (4)

Rezultatul este diferit acum. Apelul de 1 secundă a terminat primul și a tipărit "1s", urmat de "2s" și "3s". 

1s 2s 3s 4s

Rețineți că apelul de 4 secunde nu este o gorutină. Acest lucru este de proiectare, astfel încât programul așteaptă și permite gorutines termina. Fără aceasta, programul va fi imediat finalizat după lansarea gorutinelor. Există mai multe moduri, în afară de a dormi să aștepți ca o gorutină să termine.

Sincronizați Gorutinele

Un alt mod de a aștepta ca gorutinele să termine este să folosească grupuri de sincronizare. Declarați un obiect al grupului de așteptare și îl transmiteți fiecărei gorutine, care este responsabilă de apelul său Terminat() atunci când se face. Apoi așteptați grupul de sincronizare. Iată codul care adaptează exemplul anterior pentru a utiliza un grup de așteptare.

pachetul import principal ("fmt" "sync" "time") func foo (d time.Duration, wg * sync.WaitGroup) d * = 1000000000 time.Sleep (d) fmt.Println (d)  func main () var wg sync.WaitGroup wg.Add (3) go foo (3, & wg) go foo (2, & wg) go foo (1, & wg) wg.Wait

canale

Canalele le permit utilizatorilor (și programului principal) să facă schimb de informații. Puteți să creați un canal și să îl transmiteți unei gorutine. Creatorul poate scrie la canal, iar gorutina poate citi din canal. 

Și direcția opusă funcționează. Du-te oferă, de asemenea, sintaxa dulce pentru canalele cu săgeți pentru a indica fluxul de informații. Aici este o altă adaptare a programului nostru, în care gorutinele primesc un canal la care scriu când sunt terminate, iar programul principal așteaptă să primească mesaje de la toate gorutinele înainte de a termina.

pachetul import principal ("fmt" "time") func foo (d time.Durație, c chan int) d * = 1000000000 time.Sleep (d) fmt.Println <- 1  func main()  c := make(chan int) go foo(3, c) go foo(2, c) go foo(1, c) <- c <- c <- c  

Scrie un Gorutine

E un truc. Scrierea unei gorutine este aceeași cu scrierea oricărei funcții. Verificați foo () funcția de mai sus, care se numește în același program ca și o gorutină, precum și o funcție obișnuită.

3. Manipularea erorilor

După cum am menționat mai devreme, gestionarea erorilor de la Go este diferită. Funcțiile pot returna mai multe valori, iar funcțiile convenționale care pot eșua returnează un obiect de eroare ca ultima lor valoare de returnare. 

Există, de asemenea, un mecanism care seamănă cu excepțiile prin panică() și recupera() funcții, dar este cel mai potrivit pentru situații speciale. Iată un scenariu tipic de gestionare a erorilor în care bar() funcția returnează o eroare și principal() Funcția verifică dacă a apărut o eroare și o imprimă.

pachetul principal de import ("fmt" "erori") func bar () eroare returnează erorile.New ("ceva este greșit") func principal () e: e.Error ()) 

Verificarea obligatorie

Dacă atribuiți eroarea unei variabile și nu o verificați, Go va fi supărată.

func main () e: = bar () main.go: 15: e declarată și nefolosită 

Există modalități în jurul acestuia. Nu puteți atribui deloc eroarea:

func principal () bar ()

Sau îl puteți atribui sublinierii:

func principal () _ = bar ()

Suport lingvistic

Erori sunt doar valori pe care le puteți trece în mod liber. Go oferă un suport redus de erori prin declararea interfeței de eroare care necesită doar o metodă numită Eroare() care returnează un șir:

tip eroare interfață Error () string 

Există și erori pachet care vă permite să creați obiecte de eroare noi. FMT pachetul oferă un Errorf () pentru a crea obiecte de eroare formatate. E vorba de asta.

Interacțiunea cu Gorutinele

Nu puteți să returnați erori (sau orice alt obiect) dintr-o gorutină. Goruteinele pot comunica erori lumii exterioare prin intermediul unui alt mediu. Transmiterea unui canal de eroare unei gorutine este considerată o practică bună. Gorutinele pot de asemenea să scrie erori în fișierele de jurnalizare sau în baza de date sau în serviciile de apel la distanță.

Concluzie

Go a cunoscut un succes imens și un impuls în ultimii ani. Este vorba despre limba pentru sisteme și baze de date moderne distribuite (vezi ce am făcut acolo). Au fost transformați mulți dezvoltatori de Python. 

O mare parte din acesta este, fără îndoială, datorită suportului oferit de Google. Dar Go cu siguranță sta pe meritele sale. Abordarea sa în designul de limbă de bază este foarte diferită de alte limbi de programare contemporane. Incearca. Este ușor să luați și să vă distrați să vă programați.  

Cod