Shirone's Blog

Channnn Boooool

Channels are used to communicate within different goroutines. It works like pile and it is and interesting feature from Golang.

To use a channel, we need to use an arrow to point to the direction of data goes. More, we need to use make to create an new channel.

ch := make(chan int)
ch <- p    // Send variable p into the channel
s := <-ch  // Read data from the channel and assign it to s

Channels can be buffered. Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

Be careful of writing a deadlock when we are using channels. Here’s an simple example, cause they might be blocking.

type shared struct {
	mu   sync.Mutex
	data chan bool
}

func (s *shared) send() {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.data <- false

	wg.Done()
}

func (s *shared) recv() {
	s.mu.Lock()
	defer s.mu.Unlock()

	data := <-s.data
	fmt.Printf("%v\n", data)
	wg.Done()
}
func main() {
	s := shared{}
	s.data = make(chan bool, 1)

	wg.Add(2)

	go s.recv()
	time.Sleep(1)
	go s.send()

	wg.Wait()
	fmt.Println("Terminating Program")

}

The recv() function will be block by the channel (cause there are no inputs yet) while it is holding the mutex lock! And, for the send() function, it need to gain the lock before it sends the data. So, it creates a deadlock as both of the two threads are waiting for each other on some resources.

fatal error: all goroutines are asleep - deadlock!

This problem can be easily solved by exchanging the order of go s.recv() and go s.send(). But we still need to be careful when we are handling channels.

‘*’ It just took me a whole day for solving a deadlock caused by channels in my raft implementation. (。ŏ﹏ŏ)