Go Channels Tutorial

i denne vejledning skal vi se på, hvordan du kan brugekanaler i dine Go-baserede applikationer.

kanaler er rør, der forbinder mellem goroutines inden for dine Go-baserede applikationer, der tillader kommunikation og efterfølgende overførsel af værdier til og fra variabler.

de er utroligt praktiske og kan hjælpe dig med at lave utroligt højtydende,meget samtidige applikationer i Go med minimal ståhej sammenlignet med andre programmeringssprog. Dette var på ingen måde en fluke, da de designede sproget, besluttede kerneudviklerne, at de ønskede, at samtidighed inden for deres sprog skulle være en førsteklasses borger og gøre det så enkelt at arbejde med en mulig, uden at gå for langt og ikke tillade udviklere den frihed, de har brug for at arbejde i.

evnen til at lave samtidige systemer så let er noget, der trak mig til sproget i første omgang, og jeg må sige, det har været et absoluttelys hidtil.

Bemærk – Jeg vil anbefale at se på min anden tutorial ongoroutines, hvis du ønsker at læremere om goroutines.

mål

ved udgangen af denne tutorial vil du:

  • har en solid forståelse af teorien bag kanaler
  • være i stand til at oprette enkle samtidige Go-applikationer, der bruger kanaler

forudsætninger

for at gennemføre denne tutorial skal du have opfyldt følgendeforudsætninger:

  • du skal bruge Go installeret på din maskine.

Video Tutorial

hvis du ønsker det, er denne tutorial tilgængelig i videoformat.

teorien

ideen om kanaler er ikke noget nyt, ligesom mange af Go ‘s samtidige funktioner er disse begreber blevet fremført fra Hoare’ s communicating sekventielle processer (1978), CSP for kort og endda fralignende af Dijkstras bevogtede kommandoer (1975).

udviklerne af Go har imidlertid gjort det til deres mission at præsentere disse begreber på en enkel måde som muligt for at gøre det muligt for programmører at skabebedre, mere korrekte, meget samtidige applikationer.

et simpelt eksempel

lad os starte med at se, hvordan vi kan opbygge et rigtig simpelt eksempel på hvordandette virker i Go. Vi opretter først en funktion, der forsvinder og beregner anarbitrary, tilfældig værdi og sender den tilbage til en kanalvariabel kaldetvalues:

main.gå

lad os diskutere, hvad der skete her. I vores main() funktion kaldte vivalues := make(chan int), dette opkald skabte effektivt vores nye kanal, så vi efterfølgende kunne bruge det inden for vores CalculateValue goroutine.

Bemærk – Vi brugte make ved instantiering af vores values kanal som, likemaps og skiver, kanaler skal oprettes før brug.

efter at vi oprettede ud kanal, kaldte vi derefter defer close(values) hvilket henviste til lukningen af vores kanal indtil slutningen af vores main() funktionensudførelse. Dette betragtes typisk som bedste praksis for at sikre, at vi rydder op efter os selv.

efter vores opkald til defer fortsætter vi med at starte vores single goroutine:CalculateValue(values) passerer i vores nyoprettede values kanal som densparameter. Inden for vores CalculateValue funktion beregner vi en enkelt tilfældig værdi mellem 1-10, udskriver denne og sender derefter denne værdi til vores valueskanal ved at ringe values <- value.

springer tilbage i vores main() funktion, kalder vi derefter value := <-values som modtager en værdi fra vores values kanal.

Bemærk – Bemærk, hvordan når vi udfører dette program, gør det ikke straksafslut. Dette skyldes, at handlingen med at sende til og modtage fra en kanalblokerer. Vores main() funktion blokerer, indtil den modtager en værdi fra ourchannel.

ved udførelse af denne kode skal du se output se sådan ud:

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

oversigt:

myChannel := make(chan int) – opretter myChannel, som er en kanal af typenint

channel <- value – sender en værdi til en kanal

value := <- channel – modtager en værdi fra en kanal

så det ser retfærdigt ud at instantiere og bruge kanaler i dine Go-programmer, men hvad med i mere komplekse scenarier?

Unbuffered Channels

brug af en traditionel channel inden for dine goroutiner kan nogle gange føre tilproblemer med adfærd, som du måske ikke helt forventer. Med traditionelleunbuffered kanaler,når en goroutine sender en værdi til denne kanal, vil den goroutine efterfølgende blokere, indtil værdien er modtaget frakanal.

lad os se dette i et rigtigt eksempel. Hvis vi kigger på nedenstående kode, er det megetligner den kode, vi tidligere havde. Vi har dog udvidet voresCalculateValue() funktion til at udføre en fmt.Println, efter at den har sendt den tilfældigt beregnede værdi til kanalen.

i vores main() funktion har vi tilføjet et andet opkald tilgo CalculateValue(valueChannel) så vi bør forvente 2 værdier sendt til thischannel i meget hurtig rækkefølge.

main.gå

når du kører dette, skal du dog se, at kun vores første goroutines ‘ finalprint-erklæring faktisk udføres:

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

årsagen til dette er vores opfordring til c <- value har blokeret i vores secondgoroutine og efterfølgende main() funktion konkluderer det udførelse førvores andet goroutine får en chance for at fuldføre sin egen udførelse.

Buffered Channels

måden at omgå denne blokeringsadfærd er at bruge noget, der hedder abuffered channel. Disse bufferede kanaler er i det væsentlige køer af en given størrelseder kan bruges til cross-goroutine kommunikation. For at skabe abuffered kanal i modsætning til en unbuffered kanal, leverer vi en capacityargument til vores make kommando:

bufferedChannel := make(chan int, 3)

ved at ændre dette til en bufret kanal, vores send operation, c <- value onlyblocks inden for vores goroutines bør kanalen være fuld.

lad os ændre vores eksisterende program til at bruge en bufret kanal og se påoutput. Bemærk, at jeg har tilføjet et opkald til time.Sleep() nederst i voresmain() funktion for at blokere vores main() funktion nok til at tillade vores goroutiner at fuldføre udførelsen.

main.gå

nu, når vi udfører dette, skal vi se, at vores anden goroutine faktisk fortsætter sin udførelse uanset det faktum, at en anden modtagelse ikke er blevet kaldt i vores main() funktion. Takket være time.Sleep() kan vi tydeligtse forskellen mellem ikke-bufferede kanaler og deres blokerende natur og vores bufferede kanaler og deres ikke-blokerende (når de ikke er fulde) 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

konklusion

så i denne temmelig lange tutorial lykkedes det os at lære om de forskelligeforskellige typer kanaler inden for Go. Vi opdagede forskellene mellem både bufferede og ikke-bufferede kanaler, og hvordan vi kunne bruge dem til vores fordel inden for vores samtidige go-programmer.

hvis du nød denne tutorial, så er du velkommen til at lade mig vide i kommentarfeltet nedenfor. Hvis du har forslag til, hvad jeg kunne gøre bedre, så vil jeg meget gerne høre dem i kommentarfeltet nedenfor!

yderligere læsning

hvis du nød denne artikel og ønsker at lære mere om at arbejde med Samtidighedi Go, så anbefaler jeg, at du tjekker vores andre artikler om samtidighed:

  • gå Muteks Tutorial
  • gå Goroutines Tutorial
  • gå sync.Vent Gruppe Tutorial

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.

Previous post bibliotekssystem
Next post skal du male eller plette skabe? Fordele og ulemper ved hver