Go Channels Tutorial

tässä opetusohjelmassa tarkastelemme, miten voit käyttää kanavaa Go-pohjaisissa sovelluksissasi.

kanavat ovat putkia, jotka yhdistävät goroutines sinun Go-pohjaisten sovellutusten välillä, jotka mahdollistavat tiedonsiirron ja sen jälkeen arvojen siirtämisen muuttujiin ja muuttujista.

ne ovat uskomattoman käteviä ja voivat auttaa sinua tekemään uskomattoman suorituskykyisiä,erittäin samanaikaisia sovelluksia Go: ssa minimaalisella vaivalla verrattuna muihin ohjelmointikieliin. Tämä ei suinkaan ollut sattumaa, sillä kieltä suunnitellessaan ydinkehittäjät päättivät, että he halusivat oman kielensä rinnakkaisuuden olevan ensiluokkainen kansalainen ja tehdä mahdollisimman helpoksi työskennellä sen kanssa menemättä liian pitkälle ja antamatta kehittäjille heidän tarvitsemaansa vapautta työskennellä.

kyky luoda rinnakkaisia järjestelmiä niin helposti on jotain, joka veti minut kieleen alun perin, ja minun on sanottava, se on ollut ehdoton valo tähän mennessä.

huomaa – suosittelisin vilkaisemaan toista opetusohjelmaani goroutineista, jos haluat oppia lisää goroutineista.

maaleja

tämän opetusohjelman loppuun mennessä:

  • sinulla on vankka käsitys kanavien teoriasta
  • voit luoda yksinkertaisia samanaikaisia Go-sovelluksia, jotka käyttävät kanavia

Edeltävät opinnot

tämän opetusohjelman suorittamiseksi sinun on täytettävä seuraavat vaatimukset:

  • sinun tulee asentaa GO koneeseesi.

opetusvideo

jos haluat, tämä opetusvideo on saatavilla videomuodossa.

teoria

ajatus kanavista ei ole mitään uutta, sillä kuten monet Gon samanaikaiset ominaispiirteet, nämä käsitteet ovat peräisin Hoaren teoksista ”communicating Sequential Processes” (1978), lyhyesti CSP ja jopa Dijkstran vartioiduista komennoista (1975).

Go: n kehittäjät ovat kuitenkin ottaneet tehtäväkseen esitellä nämä konseptit mahdollisimman yksinkertaisella tavalla, jotta ohjelmoijat voivat luoda parempia, oikeampia ja erittäin samanaikaisia sovelluksia.

yksinkertainen esimerkki

aloitetaan katsomalla, miten voimme rakentaa todella yksinkertaisen esimerkin siitä, miten tämä toimii Go: ssa. Luomme ensin funktion, joka menee pois ja laskee anarbitraarisen, satunnaisarvon ja siirtää sen takaisin kanavamuuttujalle nimeltävalues:

main.go

Let ’ s disc the what happened here. Meidän main() funktio, kutsuimmevalues := make(chan int), tämä puhelu tehokkaasti loi uuden kanavan niin, että voisimme myöhemmin käyttää sitä meidän CalculateValue goroutine.

Huom. – käytimme make asentaessamme values kanavamme, koska kanavat on luotava ennen käyttöä.

luotuamme kanavan, soitimme sitten defer close(values), joka viivästytti kanavamme sulkemista main() funktion päättymiseen asti. Tätä pidetään yleensä parhaana käytäntönä sen varmistamiseksi, että siistiydymme itsemme jälkeen.

soitettuamme defer lähdemme polkemaan käyntiin singlemme goroutine:CalculateValue(values) ohittaen vastaperustetun values kanavamme itsesparametrina. CalculateValue – funktiossamme lasketaan yksittäinen satunnaisarvo väliltä 1-10, tulostetaan tämä ja lähetetään sitten tämä arvo values – kanavallemme kutsumalla values <- value.

hypätään takaisin meidän main() funktioon, soitetaan sitten value := <-values, joka saa arvon meidän values kanavalta.

huomaa, että kun suoritamme tämän ohjelman, se ei heti lopu. Tämä johtuu siitä, että lähetys ja vastaanottaminen kanavistaestetään. Meidän main() funktio lohkeaa, kunnes se saa arvon meidän kanavalta.

tämän koodin suorittamisen jälkeen tulosteen pitäisi näyttää jotakuinkin tältä:

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

tiivistelmä:

myChannel := make(chan int) – luo myChannel joka on kanava tyyppiint

channel <- value – lähettää arvon kanavalle

value := <- channel – saa arvon kanavalta

joten kanavien asentaminen ja käyttäminen Go-ohjelmissasi näyttää toistaiseksi reilulta, mutta entä monimutkaisemmissa skenaarioissa?

Puskuroimattomat kanavat

perinteisen channel käyttäminen goroutineissa voi joskus johtaa ongelmiin, joiden käytös ei ehkä ole aivan odotettavissa. Perinteisilläunbuffered kanavilla aina, kun yksi goroutiini lähettää tälle kanavalle arvon,kyseinen goroutiini blokkaa sen jälkeen, kunnes arvo saadaan kanavalta.

katsotaanpa tätä todellisessa esimerkissä. Jos katsomme alla olevaa koodia, se on hyvin samanlainen kuin koodi, joka meillä oli aiemmin. Olemme kuitenkin laajentaneetCalculateValue() – funktiotamme suorittamaan fmt.Println sen jälkeen, kun se on lähettänyt kanavalle sen laskennallisen arvon.

meidän main() funktio, olemme lisänneet toisen puhelungo CalculateValue(valueChannel) joten meidän pitäisi odottaa 2 arvot lähetetään tähän kanavaan hyvin nopeasti peräkkäin.

main.go

kuitenkin, Kun suoritat tämän, sinun pitäisi nähdä, että vain meidän ensimmäinen goroutines’ finalprint lauseke on todella suoritettu:

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

syynä tähän on se, että kutsumme c <- value on jumittunut kakkosgorutiinissamme ja sen jälkeen main() funktio päättää sen toteuttamisen ennen kuin toinen goroutine saa mahdollisuuden suorittaa oman teloituksensa.

puskuroidut kanavat

tämän estokäyttäytymisen voi kiertää käyttämällä jotain ns. Nämä puskuroidut kanavat ovat lähinnä tietyn kokoisia jonoja, joita voidaan käyttää rajat ylittävään viestintään. Jotta voidaan luoda ahdettu kanava vastakohtana puskuroimattomalle kanavalle, toimitamme kapasiteettiargumentin make – komennollemme:

bufferedChannel := make(chan int, 3)

jos tämä muutetaan puskuroiduksi kanavaksi, lähettämistoimenpiteenämme c <- value vain goroutiiniemme sisällä on esteitä, jos kanava on täynnä.

muokataan nykyistä ohjelmaa niin, että se käyttää puskuroitua kanavaa ja katsotaan ulostuloa. Huomaa, että olen lisännyt time.Sleep(): iinmain() – funktiomme alaosaan kutsun, jotta laiskasti estäisin main() – funktiomme sen verran, että goroutinemme ehtivät suorittaa tehtävän loppuun.

main.go

nyt, kun suoritamme tämän, meidän pitäisi nähdä, että meidän toinen goroutine ei infeedcontinue sen täytäntöönpanoa riippumatta siitä, että toinen vastaanottaa ei ole kutsuttu meidän main() funktio. time.Sleep() ansiosta voimme selvittää, mikä ero on puskuroimattomilla kanavilla ja niiden estävällä luonteella ja niiden estottomalla (kun ne eivät ole täysiä) luonteella.

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

johtopäätös

niin, tässä melko pitkä opetusohjelma, onnistuimme oppimaan erilaisia erilaisia kanavia Go. Huomasimme erot sekä puskuroitujen että puskuroimattomien kanavien välillä ja miten voisimme käyttää niitä eduksemme samanaikaisissa go-ohjelmissamme.

jos pidit tästä opetusohjelmasta, voit vapaasti kertoa minulle alla olevassa comments-osiossa. Jos sinulla on ehdotuksia siitä, mitä voisin tehdä paremmin, haluaisin kuulla ne alla olevassa kommenttiosiossa!

lisätietoja

jos pidit tästä artikkelista ja haluat oppia lisää samanaikaisesta työskentelystä, suosittelen tutustumaan muihin samanaikaisuutta käsitteleviin artikkeleihimme:

  • Go Mutex Tutorial
  • Go Goroutines Tutorial
  • Go sync.WaitGroup-Opetusohjelma

Vastaa

Sähköpostiosoitettasi ei julkaista.

Previous post Brunswickin piirikunnan kirjastojärjestelmä
Next post pitäisikö Kaapit maalata vai värjätä? Jokaisen