This article is translated
Original address: golangbot.com/buffered-ch…
What is a buffer channel?
Channels mentioned in the previous section are basically unbuffered channels. As we discussed in detail in the channels tutorial, both sending and receiving data from unbuffered channels are blocked.
We can create a channel with a buffer. Sending data blocks only when the buffer is full. Similarly, receiving data is blocked only if the buffer is empty.
You can create a channel for the buffer by passing an additional capacity parameter to the make function that specifies the size of the buffer.
ch := make(chan type, capacity)
Copy the code
The capacity in the syntax above should be greater than 0 for the channel to have buffers. Bufferless channels have a capacity of 0, so this parameter was omitted when creating channels for our previous articles.
example
package main
import (
"fmt"
)
func main(a) {
ch := make(chan string.2)
ch <- "naveen"
ch <- "paul"
fmt.Println(<- ch)
fmt.Println(<- ch)
}
Copy the code
In the code above, we create a buffer channel of capacity 2 for us. Since the channel has a capacity of 2, 2 strings can be written to the channel without blocking. We write the naveen and Paul strings to the channel, and the channel does not block. They are then read from the channel.
Program output:
naveen
paul
Copy the code
Another example
Let’s look at another example of writing data to a buffer channel in a Goroutine and reading data from that channel in the main Goroutine. This example helps us understand the buffer channel better.
package main
import (
"fmt"
"time"
)
func write(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("successfully wrote", i, "to ch")}close(ch)
}
func main(a) {
ch := make(chan int.2)
go write(ch)
time.Sleep(2 * time.Second)
for v := range ch {
fmt.Println("read value", v,"from ch")
time.Sleep(2 * time.Second)
}
}
Copy the code
In the code above, a buffer channel of capacity 2 is created and passed to write Goroutine in the main Goroutine. The main Goroutine then sleeps for two seconds. During this time, Write Goroutine was running at the same time. Write Goroutine writes the numbers 0-4 to the CH channel using the for loop. Since the capacity of the channel is only 2, the write Goroutine can write only 2 data to the channel, and will block until the channel has read at least one data.
Program output:
successfully wrote 0 to ch
successfully wrote 1 to ch
Copy the code
After printing two lines of data, the write Goroutine will be blocked until the CH channel is filled with data. Since the main Goroutine sleeps for 2 seconds before starting to read from the channel, the program prints nothing for the next 2 seconds. After sleeping for 2 seconds, the main Goroutine starts to fetch data from ch channel with for range, prints out the read data, and sleeps for 2 seconds, repeating the loop until CH channel is closed. Therefore, the program will print the following line after 2 seconds:
read value 0 from ch
successfully wrote 2 to ch
Copy the code
Loop until all values are written to the channel and closed in Write Goroutine. The final output will be:
successfully wrote 0 to ch
successfully wrote 1 to ch
read value 0 from ch
successfully wrote 2 to ch
read value 1 from ch
successfully wrote 3 to ch
read value 2 from ch
successfully wrote 4 to ch
read value 3 from ch
read value 4 from ch
Copy the code
A deadlock
package main
import (
"fmt"
)
func main(a) {
ch := make(chan string.2)
ch <- "naveen"
ch <- "paul"
ch <- "steve"
fmt.Println(<-ch)
fmt.Println(<-ch)
}
Copy the code
In the above program, we write three strings to a buffer channel of capacity 2. On the third write, the write is blocked because the channel has exceeded capacity. Now, some Goroutine must be read from the channel for the write to continue, but in this case, no concurrent routines are read from the channel. Therefore, a deadlock will occur, and the program will panic at run time.
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/tmp/sandbox091448810/prog.go:11 +0x8d
Copy the code
Length and capacity
The capacity of a buffered channel is the number of values that the channel can hold. This is the value we specified when we created the buffer channel using the make function.
The length of the buffer channel is the number of elements currently queued in it.
A program can make things clear 😀
package main
import (
"fmt"
)
func main(a) {
ch := make(chan string.3)
ch <- "naveen"
ch <- "paul"
fmt.Println("capacity is".cap(ch))
fmt.Println("length is".len(ch))
fmt.Println("read value", <-ch)
fmt.Println("new length is".len(ch))
}
Copy the code
In the code above, we create a channel of capacity 3 that can hold three strings. We then write two strings to the channel in the following code. There are now two strings queued in the channel, so the length of the channel is 2. And then we read a piece of data from the channel. There is now only one string queued in the channel, so the length of the channel is 1.
Program output:
capacity is 3
length is 2
read value naveen
new length is 1
Copy the code