Go Channels Tutorial

in deze tutorial gaan we bekijken hoe je kanalen kunt gebruiken binnen je Go-based applicaties.

kanalen zijn leidingen die een link leggen tussen goroutines binnen uw Go-baseapplicaties die communicatie en vervolgens het doorgeven van waarden naar en van variabelen mogelijk maken.

ze zijn ongelooflijk handig en kunnen u helpen bij het maken van ongelooflijk hoge prestaties,zeer gelijktijdige toepassingen in Go met minimale ophef in vergelijking met andere programmeertalen. Dit was zeker geen toeval, bij het ontwerpen van de taal besloten de kernontwikkelaars dat ze wilden dat concurrency binnen hun taal een eersteklas burger zou zijn en het zo eenvoudig mogelijk zou maken om ermee te werken, zonder te ver te gaan en ontwikkelaars niet de vrijheid te geven om in te werken.

het vermogen om gelijktijdige systemen zo gemakkelijk te maken is iets dat me in de eerste plaats tot de taal heeft aangetrokken, en ik moet zeggen, het is tot nu toe een absoluut licht geweest.

opmerking-Ik zou aanraden om eens te kijken naar mijn andere tutorial ongoroutines als je meer wilt leren over goroutines.

doelen

aan het einde van deze les zal u:

  • heb een goed begrip van de theorie achter kanalen
  • in staat zijn om eenvoudige gelijktijdige Go-toepassingen te maken die kanalen

vereisten

om deze tutorial te voltooien, moet u aan de volgende vereisten hebben voldaan:

  • u moet Go geïnstalleerd op uw machine.

videotutorial

indien u wilt, is deze tutorial beschikbaar in videoformaat.

de theorie

het idee van kanalen is niets nieuws, want zoals veel van Go ’s concurrencyfeatures, zijn deze concepten naar voren gebracht uit voorbeelden als Hoare’ s communicating Sequential Processes (1978), CSP voor kort, en zelfs uit thelikes van Dijkstra ‘ s guardired commands (1975).

de ontwikkelaars van Go hebben het echter hun missie gemaakt om deze concepten zo eenvoudig mogelijk te presenteren, zodat programmeurs betere, correctere, zeer gelijktijdige toepassingen kunnen creëren.

een eenvoudig voorbeeld

laten we beginnen met te kijken hoe we een heel eenvoudig voorbeeld kunnen opbouwen van hoe dit werkt in Go. We zullen eerst een functie creëren die verdwijnt en een willekeurige willekeurige waarde berekent en deze teruggeeft aan een kanaalvariabele genaamdvalues:

main.ga

laten we uitzoeken wat hier gebeurd is. In onze main() functie, noemden wevalues := make(chan int), deze aanroep creëerde effectief ons nieuwe kanaal zodat we het later konden gebruiken binnen onze CalculateValue goroutine.

Note-we gebruikten make bij het instantiseren van ons values kanaal als, likemaps en slices, kanalen moeten worden aangemaakt voor gebruik.

nadat we een out-kanaal hadden gemaakt, hebben we defer close(values) aangeroepen, waardoor het sluiten van ons kanaal werd uitgesteld tot het einde van de uitvoering van onze main() – functie. Dit wordt meestal beschouwd als best practice om ervoor te zorgen dat we opruimen na onszelf.

na onze oproep aan defer, gaan we verder met de aftrap van onze enkele goroutine:CalculateValue(values) die ons nieuw gecreëerde values kanaal passeert als zijn parameter. Binnen onze functie CalculateValue berekenen we een enkele willekeurige waarde tussen 1-10, printen deze uit en sturen deze waarde naar ons kanaal valuesdoor values <- valueaan te roepen.

springen we terug in onze main() functie, dan roepen we value := <-values aan, die een waarde ontvangt van ons values kanaal.

Note-merk op dat wanneer we dit programma uitvoeren, het niet directtermineert. Dit is omdat de handeling van het verzenden naar en ontvangen van een kanaal blokkeren. Onze main() functieblokken totdat het een waarde van ons kanaal ontvangt.

bij het uitvoeren van deze code ziet u de uitvoer er ongeveer zo uit:

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

samenvatting:

myChannel := make(chan int) – creëert myChannel dat is een kanaal van het typeint

channel <- value – verzendt een waarde naar een kanaal

value := <- channel – ontvangt een waarde van een kanaal

dus het installeren en gebruiken van kanalen in uw Go-programma ’s ziet er tot nu toe redelijk uit, maar hoe zit het met meer complexe scenario’ s?

niet-gebufferde kanalen

het gebruik van een traditionele channel binnen uw goroutines kan soms leiden tot problemen met gedrag dat u misschien niet helemaal verwacht. Bij traditioneleunbuffered kanalen zal goroutine, wanneer een goroutine een waarde naar dit kanaal verzendt,vervolgens blokkeren totdat de waarde van het kanaal wordt ontvangen.

laten we dit in een echt voorbeeld bekijken. Als we een blik op de onderstaande code, het is zeer vergelijkbaar met de code die we eerder hadden. Echter, we hebben onzeCalculateValue() functie uitgebreid om een fmt.Println uit te voeren nadat deze de Random berekende waarde naar het kanaal heeft gestuurd.

in onze main() functie hebben we een tweede aanroep toegevoegd aango CalculateValue(valueChannel) dus we zouden 2 waarden moeten verwachten die snel achter elkaar naar dit kanaal worden verzonden.

main.go

echter, als je dit uitvoert, zou je moeten zien dat alleen onze eerste goroutines’ finalprint statement daadwerkelijk wordt uitgevoerd:

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

de reden hiervoor is dat onze call naar c <- value geblokkeerd is in onze secondgoroutine en vervolgens concludeert de functie main() dat deze wordt uitgevoerd voordat onze tweede goroutine de kans krijgt om zijn eigen uitvoering te voltooien.

gebufferde kanalen

de manier om dit blokkeringsgedrag te omzeilen is het gebruik van het zogenaamde abuffered kanaal. Deze gebufferde kanalen zijn in wezen wachtrijen van een bepaalde grootte die kunnen worden gebruikt voor cross-goroutine communicatie. Om abuffered channel te maken in tegenstelling tot een unbuffered channel, leveren we een capacityargument aan ons make Commando:

bufferedChannel := make(chan int, 3)

door dit te veranderen naar een gebufferd kanaal, blokkeert onze Verzend operatie, c <- value alleen binnen onze goroutines als het kanaal vol is.

laten we ons bestaande programma aanpassen om een gebufferd kanaal te gebruiken en de uitvoer bekijken. Merk op dat ik een aanroep aan time.Sleep() aan de onderkant van onzemain() functie heb toegevoegd om onze main() functie lui genoeg te blokkeren zodat onze goroutines de uitvoering kunnen voltooien.

main.go

nu, wanneer we dit uitvoeren, moeten we zien dat onze tweede goroutine indeed zijn uitvoering voortzet, ongeacht het feit dat een tweede receive niet is aangeroepen in onze main() functie. Dankzij de time.Sleep() kunnen we duidelijk het verschil zien tussen niet-gebufferde kanalen en hun blokkerende aard en onze gebufferde kanalen en hun niet-blokkerende (indien niet volledig) aard.

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

conclusie

in deze vrij lange handleiding zijn we erin geslaagd om meer te weten te komen over de verschillende verschillende soorten kanalen binnen Go. We ontdekten de verschillen tussen bothbuffered en unbuffered kanalen en hoe we ze konden gebruiken om ons voordeel met onze gelijktijdige go-programma ‘ s.

als u deze tutorial leuk vond, laat het me dan weten in de opmerkingen hieronder. Als je suggesties hebt over wat ik beter zou kunnen doen dan zou ik ze graag horen in de commentaren hieronder!

verder lezen

Als u dit artikel leuk vond en meer wilt weten over het werken met concurrency in Go, dan raad ik u aan onze andere artikelen over concurrency te bekijken:

  • Go Mutex Tutorial
  • Go Goroutines Tutorial
  • Go sync.Wachtgroep Zelfstudie

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.

Previous post Brunswick County Library System
Next post moet u verf of beits kasten? Voors en tegens van elk