i denne opplæringen skal vi se på hvordan du kan bruke kanaler i Dine Go-baserte applikasjoner.
Kanaler er rør som kobler mellom goroutines
innenfor Dine Go basedapplikasjoner som tillater kommunikasjon og deretter overføring av verdier tilog fra variabler.
De er utrolig praktiske og kan hjelpe deg med å lage utrolig høy ytelse, svært samtidige applikasjoner i Go med minimal oppstyr i forhold til andreprogrammeringsspråk. Dette var på ingen måte en fluke, når du utformer thelanguage, kjernen utviklerne besluttet at de ønsket samtidig innenfor thelanguage å være en førsteklasses borger og å gjøre det så enkelt å arbeide med aspossible, uten å gå for langt og ikke tillater utviklere frihet de trenger å jobbe i.
evnen til å lage samtidige systemer så lett er noe som trakk meg til språket i utgangspunktet, og jeg må si at det har vært en absolutedelight så langt.
Merk – Jeg vil anbefale å ta en titt på min andre tutorial ongoroutines hvis du ønsker å learnmore om goroutines.
Mål
ved slutten av denne opplæringen vil du:
- Ha en solid forståelse av teorien bak kanaler
- kunne lage enkle samtidige Go-programmer som bruker kanaler
Forutsetninger
for å fullføre denne opplæringen må du ha møtt følgendeprequisites:
- Du må Gå installert på maskinen din.
Video Tutorial
hvis du ønsker, er denne opplæringen tilgjengelig i videoformat.
Teorien
ideen om kanaler er ikke noe nytt, som som Mange Av Gos samtidige funksjoner, har disse konseptene blitt fremført fra slike Som Hoare ‘scommunicating Sekvensielle Prosesser (1978), CSP for kort, og til og Med fra thelikes Of Dijkstra’ s bevoktede kommandoer (1975).
utviklerne Av Go har imidlertid gjort det til sitt oppdrag å presentere disse konseptene på en enkel måte som mulig for å gjøre det mulig for programmerere å skapebedre, mer korrekte, svært samtidige applikasjoner.
Et Enkelt Eksempel
La oss starte med å se hvordan vi kan bygge opp et veldig enkelt eksempel på howthis fungerer I Go. Vi lager først en funksjon som går bort og beregner anvilkårlig, tilfeldig verdi og sender den tilbake til en kanalvariabel kaltvalues
:
La oss disect hva som skjedde her. I vår main()
funksjon, kalt vi values := make(chan int)
, dette anropet skapte effektivt vår nye kanal, slik at vi senere kunne bruke den i vår CalculateValue
goroutine.
Merk – vi brukte
make
når instantiating vårvalues
kanal som, likemaps og skiver, kanaler må opprettes før bruk.
etter at vi opprettet kanal, ringte vi defer close(values)
whichdeferred lukking av kanalen vår til slutten av vår main()
function ‘ sexecution. Dette anses vanligvis som beste praksis for å sikre at vi rydder oppetter oss selv.
Etter vår samtale til defer
, vi går på å sparke i gang vår enkelt goroutine:CalculateValue(values)
passerer i vår nyopprettede values
kanal som itsparameter. I vår CalculateValue
– funksjon beregner vi en enkelt randomvalue mellom 1-10, skriver ut dette og sender denne verdien til vår values
– kanal ved å ringe values <- value
.
Hopper tilbake til vår main()
funksjon, kaller vi value := <-values
som mottar en verdi fra vår values
kanal.
Merk-Legg merke til hvordan når vi utfører dette programmet, gjør det ikke umiddelbart. Dette skyldes at handlingen med å sende til og motta fra en kanal blokkerer. Våre
main()
funksjonsblokker til den mottar en verdi fra ourchannel.
ved utførelse av denne koden, bør du se utgangen ser omtrent slik ut:
$ go run main.goGo Channel TutorialCalculated Random Value: {} 77
Sammendrag:
myChannel := make(chan int)
– oppretter myChannel som er en kanal av typenint
channel <- value
– sender en verdi til en kanal
value := <- channel
– mottar en verdi fra en kanal
så, instantiating og bruk av kanaler I Dine go-programmer ser fairlystraightforward så langt, men hva med i mer komplekse scenarier?
Ubufrede Kanaler
Bruk av en tradisjonell channel
i goroutinene dine kan noen ganger føre til problemer med atferd som du kanskje ikke forventer. Med tradisjonelle unbuffered
kanaler,når en goroutine sender en verdi til denne kanalen, vil goroutine senere blokkere til verdien mottas fra kanalen.
La oss se dette i et reelt eksempel. Hvis vi ser på koden nedenfor, er det veldigligner på koden som vi tidligere hadde. Vi har imidlertid utvidet vår CalculateValue()
– funksjon for å utføre en fmt.Println
etter at den har sendt den beregnede verdien til kanalen.
i vår main()
funksjon, har vi lagt til en andre samtale til go CalculateValue(valueChannel)
så vi bør forvente 2 verdier sendt til thiskanal i svært rask rekkefølge.
men når du kjører dette, bør du se at bare vår første goroutines ‘ finalprint-setning faktisk utføres:
go run main.goGo Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 71Only Executes after another goroutine performs a receive on the channel
årsaken til dette er at vårt kall til c <- value
har blokkert i vår secondgoroutine, og deretter avslutter funksjonen main()
sin utførelse førvår andre goroutine
får en sjanse til å fullføre sin egen utførelse.
Bufrede Kanaler
måten å komme seg rundt denne blokkeringsadferden er å bruke noe som kalles abuffered channel. Disse bufrede kanaler er i hovedsak køer av en gitt sizethat kan brukes for cross-goroutine kommunikasjon. For å skape abufret kanal i motsetning til en ubufret kanal, leverer vi en capacityargument til vår make
kommando:
bufferedChannel := make(chan int, 3)
ved å endre dette til en bufret kanal, vår send operasjon, c <- value
onlyblocks innenfor våre goroutines bør kanalen være full.
la oss endre vårt eksisterende program for å bruke en bufret kanal og ta en titt påutgangen. Legg merke til at jeg har lagt til et anrop til time.Sleep()
nederst i vår main()
– funksjon for å blokkere vår main()
– funksjon nok til å tillate goroutines å fullføre utførelsen.
Nå, Når vi utfører dette, bør Vi se at vår andre goroutine faktisk fortsetter utførelsen uavhengig av det faktum at en annen mottak ikke har blitt kalt i vår main()
funksjon. Takket være time.Sleep()
kan vi tydeligse forskjellen mellom ubufrede kanaler og deres blokkerende natur og våre bufrede kanaler og deres ikke-blokkerende (når ikke full) natur.
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
Konklusjon
så i denne ganske lange opplæringen klarte vi å lære om de ulikedistinct typer kanaler innen Go. Vi oppdaget forskjellene mellom bothbuffered og unbuffered kanaler og hvordan vi kunne bruke dem til vår advantagewithin våre samtidige go-programmer.
hvis du likte denne opplæringen, så kan du gjerne gi meg beskjed i thecomments delen nedenfor. Hvis du har noen forslag til hva jeg kunne gjøre bedre, så vil jeg gjerne høre dem i kommentarfeltet nedenfor!
Videre Lesing
hvis du likte denne artikkelen Og ønsker å lære mer om å jobbe Med Concurrencyin Go, så anbefaler jeg at du sjekker ut våre andre artikler om concurrency:
- Gå Mutex Tutorial
- Gå Goroutines Tutorial
- gå sync.WaitGroup Tutorial