Dowiedz się, jak gorutyny i kanały umożliwiają wydajną współbieżność w programach Go.

Współbieżność jest kluczowym aspektem nowoczesnego tworzenia oprogramowania, ponieważ umożliwia programom wydajną obsługę wielu zadań jednocześnie. Możesz pisać programy, które wykonują różne operacje prowadzące do poprawy wydajności, szybkości reakcji i wykorzystania zasobów.

Współbieżność jest jedną z cech odpowiedzialnych za szybką adopcję Go. Wbudowana w Go obsługa programowania współbieżnego jest uważana za prostą, a jednocześnie pomaga uniknąć typowych pułapek, takich jak warunki wyścigu i zakleszczenia.

Współbieżność w Go

Go zapewnia solidne wsparcie dla współbieżności poprzez różne mechanizmy, wszystkie dostępne w standardowej bibliotece i łańcuchu narzędzi. Idź programy osiągnąć współbieżność za pomocą goroutines i kanałów.

Goroutines to lekkie, niezależnie wykonujące funkcje, które działają równolegle z innymi goroutines w tej samej przestrzeni adresowej. Goroutines umożliwiają jednoczesne wykonywanie wielu zadań bez jawnego zarządzania wątkami. Goroutines są lżejsze niż wątki systemu operacyjnego, a Go może wydajnie obsługiwać tysiące, a nawet miliony goroutines jednocześnie.

instagram viewer

Kanały to mechanizm komunikacji służący do koordynacji i wymiany danych między gorutynami. Kanał to typowany kanał, który umożliwia gorutynom wysyłanie i odbieranie wartości. Kanały zapewniają synchronizację, aby zapewnić bezpieczne udostępnianie danych między gorutynami, jednocześnie zapobiegając warunkom wyścigu i innym typowym problemom z współbieżnością.

Łącząc goroutines i kanały, Go zapewnia potężny i prosty model współbieżności, który upraszcza tworzenie współbieżnych programów przy jednoczesnym zachowaniu bezpieczeństwa i wydajności. Mechanizmy te umożliwiają łatwe korzystanie procesory wielordzeniowe i tworzyć wysoce skalowalne i responsywne aplikacje.

Jak używać Goroutines do współbieżnego wykonywania kodu

Środowisko wykonawcze Go zarządza goroutines. Goroutines mają swój stos, co pozwala im mieć lekki ślad przy początkowym rozmiarze stosu wynoszącym kilka kilobajtów.

Goroutines są multipleksowane na kilka wątków systemu operacyjnego przez środowisko uruchomieniowe Go. Harmonogram środowiska uruchomieniowego Go planuje je w dostępnych wątkach, wydajnie rozdzielając obciążenie, umożliwiając jednoczesne wykonywanie wielu gorutyn na mniejszej liczbie wątków systemu operacyjnego.

Tworzenie gorutyn jest proste. Użyjesz Iść słowo kluczowe, po którym następuje wywołanie funkcji w celu zadeklarowania gorutyn.

funkcjagłówny() {
Iść funkcja1() // Utwórz i wykonaj goroutine dla funkcji1
Iść funkcja2() // Utwórz i wykonaj goroutine dla funkcji2

// ...
}

funkcjafunkcja1() {
// Kod dla funkcji1
}

funkcjafunkcja2() {
// Kod dla funkcji2
}

Kiedy program wywołuje funkcja1() I funkcja2() z Iść słowo kluczowe, środowisko uruchomieniowe Go wykonuje funkcje jednocześnie jako goroutines.

Oto przykład użycia goroutine, która wypisuje tekst na konsoli:

pakiet główny

import (
"fmt"
"czas"
)

funkcjadrukujTekst() {
Do ja := 1; ja <= 5; i++ {
fmt. println(„Drukowanie tekstu”, I)
czas. Spać(1 * czas. Drugi)
}
}

funkcjagłówny() {
Iść printText() // Uruchom goroutine, aby jednocześnie wykonać funkcję printText

// Wykonaj inne zadania w głównym goroutine
Do ja := 1; ja <= 5; i++ {
fmt. println(„Wykonywanie innych zadań”, I)
czas. Spać(500 * czas. milisekunda)
}

// Poczekaj na zakończenie goroutine
czas. Spać(6 * czas. Drugi)
}

The drukujTekst funkcja wielokrotnie drukuje jakiś tekst na konsoli za pomocą a Do pętla, która działa pięć razy po jednosekundowym opóźnieniu między każdą instrukcją z pakiet czasu.

The główny funkcja uruchamia goroutine przez wywołanie idź printText, który uruchamia drukujTekst funkcjonować jako oddzielna współbieżna gorutyna, która umożliwia wykonywanie funkcji współbieżnie z resztą kodu w główny funkcjonować.

Wreszcie, aby upewnić się, że program nie zakończy się przed drukujTekst goroutine kończy, czas. Spać funkcja wstrzymuje główną goroutine na sześć sekund. W rzeczywistych scenariuszach używałbyś mechanizmów synchronizacji, takich jak kanały lub grupy oczekujących, do koordynowania wykonywania goroutines.

Używanie kanałów do komunikacji i synchronizacji

Goroutines mają wbudowaną obsługę komunikacji i synchronizacji przez kanały, dzięki czemu pisanie jest współbieżne kod łatwiejszy niż tradycyjne wątki, które często wymagają ręcznych mechanizmów synchronizacji, takich jak blokady i semafory.

Kanały można traktować jako potoki do przepływu danych między gorutynami. Jeden goroutine może wysłać wartość do kanału, a inny goroutine może odebrać tę wartość z kanału. Mechanizm ten zapewnia bezpieczną i zsynchronizowaną wymianę danych.

Użyjesz operatora do wysyłania i odbierania danych za pośrednictwem kanałów.

Oto przykład demonstrujący podstawowe użycie kanałów do komunikacji między dwoma gorutynami:

funkcjagłówny() {
// Utwórz niebuforowany kanał typu string
ch := robić(chanstrunowy)

// Goroutine 1: Wysyła wiadomość do kanału
Iśćfunkcja() {
ch "Cześć, kanał!"
}()

// Goroutine 2: Odbiera wiadomość z kanału
wiad := fmt. Println (wiadomość) // Dane wyjściowe: Witaj, kanale!
}

Kanał w główny funkcja jest niebuforowanym kanałem o nazwie rozdz stworzony z robić() funkcjonować. Pierwszy goroutine wysyła wiadomość „Hello, Channel!” do kanału za pomocą operatora, a druga gorutyna odbiera wiadomość z kanału korzystającego z tego samego operatora. Wreszcie, główny funkcja drukuje otrzymaną wiadomość na konsoli.

Możesz zdefiniować określone kanały. Typ kanału określisz podczas tworzenia. Oto przykład ilustrujący użycie różnych typów kanałów:

funkcjagłówny() {
// Niebuforowany kanał
ch1 := robić(chanint)

// Buforowany kanał o pojemności 3
oł2 := robić(chanstrunowy, 3)

// Wysyłanie i odbieranie wartości z kanałów
kanał 1 42// Wyślij wartość do ch1
wartość1 := // Odbierz wartość z kanału 1

kanał 2 "Cześć"// Wyślij wartość do ch2
wartość2 := // Odbierz wartość z kanału 2
}

The główny funkcja tworzy dwa kanały: kanał 1 jest niebuforowanym kanałem całkowitym, podczas gdy kanał 2 jest buforowanym kanałem łańcuchowym o pojemności 3. Możesz wysyłać i odbierać wartości do i z tych kanałów za pomocą operator (wartości muszą być określonego typu).

Kanałów można używać jako mechanizmów synchronizacji do koordynowania wykonywania goroutine, wykorzystując blokujący charakter operacji na kanałach.

funkcjagłówny() {
ch := robić(chanbool)

Iśćfunkcja() {
fmt. println(„Gorutyna 1”)
ch PRAWDA// Zakończenie sygnału
}()

Iśćfunkcja() {
// Poczekaj na sygnał zakończenia od Goroutine 1
fmt. println(„Gorutyna 2”)
}()

// Poczekaj na sygnał zakończenia od Goroutine 2
fmt. println(„Główna gorutyna”)
}

The rozdz kanał jest logiczny. Dwie goroutines działają jednocześnie w główny funkcjonować. Goroutine 1 sygnalizuje zakończenie, wysyłając a PRAWDA wartość do kanału rozdz. Goroutine 2 czeka na sygnał zakończenia, odbierając wartość z kanału. Na koniec główny goroutine czeka na sygnał zakończenia od goroutine dwa.

Możesz tworzyć aplikacje internetowe w Go With Gin

Możesz tworzyć wydajne aplikacje internetowe w Go z Gin, wykorzystując funkcje współbieżności Go.

Możesz użyć Gin do wydajnej obsługi routingu HTTP i oprogramowania pośredniczącego. Wykorzystaj wbudowaną obsługę współbieżności w Go, stosując gorutyny i kanały do ​​zadań takich jak zapytania do bazy danych, wywołania API lub inne operacje blokujące.