110

I'm trying to create an asynchronous channel and I've been looking at http://golang.org/ref/spec#Making_slices_maps_and_channels.

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

What does it mean that the buffer size is 10? What specifically does the buffer size represent/limit?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Tech163
  • 4,176
  • 8
  • 33
  • 36

3 Answers3

204

The buffer size is the number of elements that can be sent to the channel without the send blocking. By default, a channel has a buffer size of 0 (you get this with make(chan int)). This means that every single send will block until another goroutine receives from the channel. A channel of buffer size 1 can hold 1 element until sending blocks, so you'd get

c := make(chan int, 1)
c <- 1 // doesn't block
c <- 2 // blocks until another goroutine receives from the channel
Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 27
    Good answer. Effective Go has a nice chapter titled "Concurrency" that expounds on channels. Highly recommended: http://golang.org/doc/effective_go.html – Levi Aug 14 '12 at 02:26
  • Im messing around with this and make(chan int, 1) allows 3 values to be passed into my channel before blocking(testing it with log.Printlns), and the default is letting 2 in before blocking. Any idea why: – Mauricio Jun 13 '17 at 22:35
  • @Mauricio That sounds pretty weird. I just tested using Go 1.8.3 locally, and also using the "Try Go" functionality at https://golang.org, and in both cases it still behaves as documented in my answer. – Lily Ballard Jun 14 '17 at 23:30
  • 1
    I appreciate the response, but I was actually misinterpreting the data printing to my console. It does work like you described. – Mauricio Jun 15 '17 at 03:03
21

The following code illustrates the blocking of unbuffered channel:

// 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)

You may play with the code here.

Vladimir Bauer
  • 685
  • 7
  • 10
2
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)
}

result:

receive messages 444 from the channel

Elapsed using zero_buffer channel: 505.6729ms

Elapsed using non zero_buffer channel: 0s

Yahya Hussein
  • 8,767
  • 15
  • 58
  • 114