Go Channels Tutorial

In questo tutorial, ci accingiamo a guardare come è possibile usechannels all’interno delle applicazioni Go-based.

I canali sono pipe che collegano tra goroutines all’interno delle applicazioni Go basedapplications che consentono la comunicazione e successivamente il passaggio di valori a e dalle variabili.

Sono incredibilmente maneggevoli e possono aiutarti a creare applicazioni incredibilmente performanti e altamente simultanee in Go con il minimo sforzo rispetto ad altri linguaggi di programmazione. Questo non era affatto un colpo di fortuna, quando si progettava thelanguage, gli sviluppatori principali decisero che volevano che la concorrenza all’interno di theirlanguage fosse un cittadino di prima classe e rendesse il più semplice possibile lavorare con loro, senza andare troppo lontano e non permettendo agli sviluppatori la libertà in cui hanno bisogno di lavorare.

La capacità di creare sistemi simultanei così facilmente è qualcosa che mi ha attirato in primo luogo sul linguaggio, e devo dire che finora è stata una luce assoluta.

Nota – Consiglierei di dare un’occhiata al mio altro tutorial ongoroutine se desideri impararedi più su goroutine.

Obiettivi

alla fine di questo tutorial, vi:

  • Avere una solida comprensione di come la teoria dietro canali
  • Essere in grado di creare semplici concorrenti applicazioni che utilizzano canali

Prerequisiti

per completare questa esercitazione, è necessario avere incontrato il followingprerequisites:

  • avrete bisogno di Andare installato sulla vostra macchina.

Video Tutorial

Se lo si desidera, questo tutorial è disponibile in formato video.

The Theory

L’idea dei canali non è nulla di nuovo, poiché come molte delle caratteristiche simultanee di Go, questi concetti sono stati portati avanti da artisti del calibro di Hoare’Communicating Sequential Processes (1978), CSP in breve, e anche da thelikes of Dijkstra guarded commands (1975).

Gli sviluppatori di Go, tuttavia, hanno fatto la loro missione di presentare questi concetti in modo semplice possibile per consentire ai programmatori di creare applicazioni migliori, più corrette e altamente concorrenti.

Un semplice esempio

Iniziamo vedendo come possiamo costruire un esempio davvero semplice di comequesto funziona in Go. Creeremo prima una funzione che va via e calcola un valore arbitrario e casuale e lo passa a una variabile di canale chiamatavalues:

principale.go

Vediamo cosa è successo qui. Nella nostra funzione main(), abbiamo chiamatovalues := make(chan int), questa chiamata ha effettivamente creato il nostro nuovo canale in modo da poterlo utilizzare successivamente all’interno della nostra goroutine CalculateValue.

Nota – Abbiamo usato make quando abbiamo istanziato il nostro canale values poiché, come mappe e sezioni, i canali devono essere creati prima dell’uso.

Dopo aver creato il canale, abbiamo quindi chiamato defer close(values) whichdeferred la chiusura del nostro canale fino alla fine del nostro main() function’sexecution. Questo è in genere considerato best practice per garantire che abbiamo riordinare upafter noi stessi.

Dopo la nostra chiamata a defer, continuiamo a dare il via alla nostra singola goroutine:CalculateValue(values) passando nel nostro canale appena creato values come parametro. All’interno della nostra funzione CalculateValue, calcoliamo un singolo randomvalue tra 1-10, lo stampiamo e quindi inviamo questo valore al nostro canale valueschiamando values <- value.

Saltando di nuovo nella nostra funzione main(), chiamiamo quindi value := <-values chericeve un valore dal nostro canale values.

Nota-Si noti come quando eseguiamo questo programma, non immediatelyterminate. Questo perché l’atto di inviare e ricevere da un channelare blocco. Il nostro main() blocchi funzione fino a quando non riceve un valore da ourchannel.

All’esecuzione di questo codice, dovresti vedere l’output simile a questo:

$ go run main.goGo Channel TutorialCalculated Random Value: {} 77

Sommario:

myChannel := make(chan int) – crea myChannel che è un canale di tipoint

channel <- value – invia un valore di un canale

value := <- channel – riceve un valore da un canale

Quindi, creare un’istanza e l’utilizzo di canali del Go programmi sembra fairlystraightforward finora, ma che cosa circa in scenari più complessi?

Canali unbuffered

L’utilizzo di un tradizionale channel all’interno delle tue goroutine a volte può portare a problemi con un comportamento che potresti non aspettarti. Con i canali tradizionaliunbuffered, ogni volta che una goroutine invia un valore a questo canale, la goroutine verrà successivamente bloccata fino a quando il valore non viene ricevuto dal canale.

Vediamo questo in un esempio reale. Se diamo un’occhiata al codice sottostante, è moltosimile al codice che avevamo in precedenza. Tuttavia, abbiamo esteso la nostra funzioneCalculateValue() per eseguire un fmt.Println dopo che ha inviato il suo valore calcolato in modo casuale al canale.

Nella nostra funzione main(), abbiamo aggiunto una seconda chiamata ago CalculateValue(valueChannel) quindi dovremmo aspettarci 2 valori inviati a thischannel in rapida successione.

principale.vai

Tuttavia, quando si esegue questa operazione, si dovrebbe vedere che solo il nostro primo goroutines’ finalprint dichiarazione viene effettivamente eseguito:

go run main.goGo Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 71Only Executes after another goroutine performs a receive on the channel

La ragione di questo è la nostra chiamata a c <- value ha bloccato nel nostro secondgoroutine e, successivamente, il main() funzione si conclude l’esecuzione beforeour secondo goroutine ottiene la possibilità di completare la sua esecuzione.

Canali bufferizzati

Il modo per aggirare questo comportamento di blocco è usare qualcosa chiamato canale alterato. Questi canali bufferizzati sono essenzialmente code di una determinata dimensione che possono essere utilizzate per la comunicazione cross-goroutine. Per creare un canale alterato rispetto a un canale non soffiato, forniamo un capacityargument al nostro comando make :

bufferedChannel := make(chan int, 3)

Cambiando questo in un canale bufferizzato, la nostra operazione di invio, c <- value blocca solo all’interno delle nostre goroutine se il canale è pieno.

Modifichiamo il nostro programma esistente per utilizzare un canale bufferizzato e dare un’occhiata all’output. Si noti che ho aggiunto una chiamata a time.Sleep() nella parte inferiore della nostra funzionemain() per bloccare pigramente la nostra funzione main() abbastanza da consentire alle nostre goroutine di completare l’esecuzione.

principale.go

Ora, quando eseguiamo questo, dovremmo vedere che la nostra seconda goroutine continua effettivamente la sua esecuzione indipendentemente dal fatto che una seconda ricezione non sia stata chiamata nella nostra funzione main(). Grazie a time.Sleep(), possiamo vedere chiaramente la differenza tra i canali non soffiati e la loro natura bloccante e i nostri canali soffiati e la loro natura non bloccante (quando non piena).

Go Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 77This executes regardless as the send is now non-blockingThis executes regardless as the send is now non-blocking

Conclusione

Quindi, in questo tutorial abbastanza lungo, siamo riusciti a conoscere i vari tipi di canali distinti all’interno di Go. Abbiamo scoperto le differenze tra i canali bothbuffered e unbuffered e come potremmo usarli a nostro vantaggio nei nostri programmi go concorrenti.

Se ti è piaciuto questo tutorial, quindi non esitate a farmelo sapere nella sezione thecomments qui sotto. Se avete suggerimenti su cosa potrei fare betterthen mi piacerebbe sentirli nella sezione commenti qui sotto!

Ulteriori letture

Se ti è piaciuto questo articolo e desideri saperne di più su come lavorare con Concurrencyin Go, ti consiglio di controllare i nostri altri articoli sulla concorrenza:

  • Vai Mutex Tutorial
  • Vai Goroutine Tutorial
  • Vai sync.WaitGroup Tutorial

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Previous post Brunswick County Library System
Next post Si dovrebbe dipingere o macchiare armadi? Pro e contro di ogni