Go Channels Tutorial

ebben az oktatóanyagban megvizsgáljuk, hogyan használhatja a csatornákat a Go-alapú alkalmazásokban.

a csatornák olyan csövek, amelyek összekapcsolják a goroutines között a Go basedapplications-en belül, amelyek lehetővé teszik a kommunikációt, majd az értékek átadását a változókból.

ezek hihetetlenül praktikus,és segít kézműves hihetetlenül nagy teljesítményű, nagyon egyidejű alkalmazások Go minimális felhajtás képest más programozási nyelvek. Ez egyáltalán nem volt véletlen, a nyelv megtervezésekor a fő fejlesztők úgy döntöttek, hogy azt akarják, hogy a nyelvükön belüli párhuzamosság első osztályú állampolgár legyen, és hogy a lehető legegyszerűbbé tegyék a munkát, anélkül, hogy túl messzire mennének, és nem engednék meg a fejlesztőknek azt a szabadságot, amelyben dolgozniuk kell.

az a képesség, hogy az egyidejű rendszereket ilyen könnyen el lehet készíteni, elsősorban a nyelv vonzotta, és azt kell mondanom, ez eddig abszolút öröm volt.

megjegyzés – azt javasoljuk, hogy vessen egy pillantást a többi bemutató ongoroutines ha szeretné, hogy learnmore körülbelül goroutines.

célok

a bemutató végére:

  • van egy szilárd megértése, hogy az elmélet mögött csatornák
  • legyen képes létrehozni egyszerű egyidejű Go alkalmazásokat használó csatornák

előfeltételek

annak érdekében, hogy teljes ez a bemutató, akkor meg kell felelnie a következő előfeltételei:

  • szüksége lesz Go telepítve a gépen.

videó bemutató

ha szeretné, ez a bemutató elérhető videó formátumban.

az elmélet

a csatornák gondolata nem új keletű, mivel a GO sok egyidejűségjellemzőjéhez hasonlóan ezeket a fogalmakat a Hoare ‘s communicating Sequential Processes (1978), röviden CSP, sőt a Dijkstra’ s őrzött parancsok (1975).

a GO fejlesztői azonban küldetésükké tették, hogy ezeket a fogalmakat a lehető legegyszerűbb módon mutassák be, hogy lehetővé tegyék a programozók számára, hogy jobb, helyesebb, erősen párhuzamos alkalmazásokat hozzanak létre.

egyszerű példa

kezdjük azzal, hogy megnézzük, hogyan építhetünk fel egy nagyon egyszerű példát arra, hogy ez hogyan működik a Go-ban. Először létrehozunk egy függvényt, amely eltűnik, kiszámítja az anarbitrary, random értéket, majd visszaadja egy csatorna változónakvalues:

fő.go

vizsgáljuk meg, mi történt itt. A mi main() funkció, hívtukvalues := make(chan int), ez a hívás hatékonyan létre az új csatorna sothat tudtuk később használni belül a CalculateValue goroutine.

megjegyzés – a make – ot használtuk a values csatornánk példányosításakor, mivel a likemaps és slices csatornákat használat előtt létre kell hozni.

miután létrehoztuk a csatornát, felhívtuk az defer close(values) – et, amely korlátozta csatornánk bezárását a main() funkció végrehajtásának végéig. Ezt általában a legjobb gyakorlatnak tekintik annak biztosítására, hogy rendet tegyünk magunk után.

miután felhívtuk a defer – et, elindítjuk az egyetlen goroutine-t:CalculateValue(values) az újonnan létrehozott values csatornánkon áthaladva itsparameterként. A CalculateValue függvényen belül kiszámítunk egy véletlenszerű értéket 1-10 között, kinyomtatjuk ezt, majd elküldjük ezt az értéket a valuescsatornánknak a values <- valuehívásával.

visszaugrunk a main() funkciónkba, majd meghívjuk a value := <-values – ot, amely értéket kap a values csatornánkból.

Megjegyzés – figyelje meg, hogy amikor végrehajtjuk ezt a programot, akkor nem azonnal véget ér. Ez azért van, mert a csatorna küldésének és fogadásának aktusa blokkolva van. A main() függvény blokkol, amíg nem kap értéket a ourchannel – től.

ennek a kódnak a végrehajtásakor látnia kell, hogy a kimenet valahogy így néz ki:

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

összefoglaló:

myChannel := make(chan int) – létrehozza a myChannel-t, amely egy típusú csatornaint

channel <- value – értéket küld egy csatornának

value := <- channel – értéket kap egy csatornától

tehát a csatornák példányosítása és használata a Go programokban eddig meglehetősen egyszerűnek tűnik, de mi a helyzet a bonyolultabb forgatókönyvekkel?

nem pufferelt csatornák

a hagyományos channel használata a goroutinokon belül néha olyan viselkedéshez vezethet, amelyre nem biztos, hogy számít. A hagyományosunbuffered csatornáknál, amikor egy goroutine értéket küld erre a csatornára,akkor a goroutine ezt követően blokkolja, amíg az érték meg nem érkezik a csatornától.

lássuk ezt egy valós példában. Ha megnézzük az alábbi kódot, akkor nagyonhasonlóan a korábban használt kódhoz. Azonban kiterjesztettük aCalculateValue() függvényünket egy fmt.Println végrehajtására, miután elküldte a véletlenszerűen kiszámított értéket a csatornának.

a mi main() függvény, már hozzá egy második hívástgo CalculateValue(valueChannel) tehát meg kell várni 2 értékek küldött thischannel nagyon gyors egymásutánban.

fő.go

ennek futtatásakor azonban látnia kell, hogy csak az első goroutines finalprint utasításunk kerül végrehajtásra:

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

ennek az az oka, hogy a hívás c <- value blokkolta a mi secondgorutine és ezt követően a main() függvény arra a következtetésre jut, hogy a végrehajtás előtt a második goroutine kap egy esélyt, hogy befejezze a saját végrehajtását.

pufferelt csatornák

a blokkoló viselkedés megkerülésének módja az úgynevezett abuffered channel használata. Ezek a pufferelt csatornák lényegében egy adott méretű sorok, amelyek felhasználhatók a goroutin közötti kommunikációhoz. Annak érdekében, hogy abuffered csatornát hozzunk létre, szemben a nem pufferelt csatornával, kapacitási argumentumot adunk a make parancshoz:

bufferedChannel := make(chan int, 3)

ha ezt pufferelt csatornára változtatjuk, a küldési műveletünk c <- value onlyblocks a goroutinjainkon belül, ha a csatorna megtelt.

módosítsuk meglévő programunkat egy pufferelt csatorna használatára, és nézzük meg a kimenetet. Figyeljük meg, hogy már hozzá egy hívást time.Sleep() alján amain() funkció annak érdekében, hogy lustán blokkolja a main() funkció elég allowour goroutines teljes végrehajtását.

fő.go

Most, amikor ezt végrehajtjuk, látnunk kell, hogy a második gorutinunk valóban folytatja a végrehajtását, függetlenül attól, hogy a második fogadás nem volt hívva a main() függvényünkben. A time.Sleep()-nek köszönhetően világosan láthatjuk a különbséget a nem pufferelt csatornák és azok blokkoló jellege, valamint a mi pufferelt csatornáink és azok nem blokkoló (ha nem teljes) jellege között.

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

következtetés

tehát ebben a meglehetősen hosszú oktatóanyagban sikerült megismerkednünk a Go különböző csatornatípusaival. Felfedeztük a különbségeket mind a pufferelt, mind a nem pufferelt csatornák között, és hogyan használhatnánk őket előnyünkre a párhuzamos go programjainkban.

ha tetszett ez a bemutató, akkor nyugodtan tudassa velem az alábbi megjegyzések részben. Ha bármilyen javaslata van arról, hogy mit tehetnék jobban, akkor szeretném hallani őket az alábbi megjegyzések részben!

további olvasmányok

ha tetszett ez a cikk, és szeretne többet megtudni a Concurrencyin Go – val való együttműködésről, akkor azt javaslom, hogy nézze meg a konkurenciáról szóló többi cikkünket:

  • Go Mutex bemutató
  • Go Goroutines bemutató
  • Go szinkronizálás.WaitGroup Bemutató

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.

Previous post Brunswick megyei könyvtári rendszer
Next post festenie vagy festenie kell a szekrényeket? Előnyök & hátrányok minden