Jaki jest rozmiar bufora kanału?

86

Próbuję utworzyć kanał asynchroniczny i patrzyłem na http://golang.org/ref/spec#Making_slices_maps_and_channels .

c := make(chan int, 10)         // channel with a buffer size of 10

Co to znaczy, że rozmiar bufora wynosi 10? Co konkretnie reprezentuje / ogranicza rozmiar bufora?

Tech163
źródło
Zobacz tutaj i dalej
Ivan Black
Zobacz tutaj również pomocne. Bardzo proste i łatwe do zrozumienia :)
Ardi Nusawan

Odpowiedzi:

161

Rozmiar bufora to liczba elementów, które można wysłać do kanału bez blokowania wysyłania. Domyślnie kanał ma rozmiar bufora równy 0 (dostajesz to z make(chan int)). Oznacza to, że każda pojedyncza wysyłka będzie blokowana, dopóki inna goroutine nie otrzyma z kanału. Kanał o rozmiarze bufora 1 może pomieścić 1 element do momentu wysłania bloków, więc otrzymasz

c := make(chan int, 1)
c <- 1 // doesn't block
c <- 2 // blocks until another goroutine receives from the channel
Lily Ballard
źródło
21
Dobra odpowiedź. Effective Go ma fajny rozdział zatytułowany „Współbieżność”, który objaśnia kanały. Gorąco polecam: golang.org/doc/effective_go.html
Levi,
Ja się z tym bawię i make (chan int, 1) pozwala na przesłanie 3 wartości do mojego kanału przed zablokowaniem (testowanie go za pomocą log.Printlns), a domyślnie wpuszczanie 2 przed zablokowaniem. Każdy pomysł, dlaczego:
Mauricio
@Mauricio To brzmi dość dziwnie. Właśnie przetestowałem lokalnie używając Go 1.8.3, a także używając funkcji „Wypróbuj Go” na golang.org i w obu przypadkach nadal zachowuje się tak, jak opisano w mojej odpowiedzi.
Lily Ballard
1
Doceniam odpowiedź, ale właściwie źle zinterpretowałem dane drukowane na mojej konsoli. Działa tak, jak opisałeś.
Mauricio
10

Poniższy kod ilustruje blokowanie niebuforowanego kanału:

// to see the diff, change 0 to 1
c := make(chan struct{}, 0)
go func() {
    time.Sleep(2 * time.Second)
    <-c
}()
start := time.Now()
c <- struct{}{} // block, if channel size is 0
elapsed := time.Since(start)
fmt.Printf("Elapsed: %v\n", elapsed)

Możesz pobawić się kodem tutaj .

Vladimir Bauer
źródło
0
package main

import (
    "fmt"
    "time"
)

func receiver(ch <-chan int) {
    time.Sleep(500 * time.Millisecond)
    msg := <-ch
    fmt.Printf("receive messages  %d from the channel\n", msg)
}

func main() {
    start := time.Now()
    zero_buffer_ch := make(chan int, 0)
    go receiver(zero_buffer_ch)
    zero_buffer_ch <- 444
    elapsed := time.Since(start)    
    fmt.Printf("Elapsed using zero_buffer channel: %v\n", elapsed)

    restart := time.Now()
    non_zero_buffer_ch := make(chan int, 1)
    go receiver(non_zero_buffer_ch)
    non_zero_buffer_ch <- 4444
    reelapsed := time.Since(restart)
    fmt.Printf("Elapsed using non zero_buffer channel: %v\n", reelapsed)
}

wynik:

odbierać wiadomości 444 z kanału

Upłynęło przy użyciu kanału zero_buffer: 505,6729ms

Upłynęło przy użyciu kanału niezerowego bufora: 0s

user2480972
źródło