Golang implements directional channel

Time:2022-5-4

Channels can be directional(directional)。 By default, channels will be bi-directional(bidirectional)In formal operation, users can either put the value into the channel or take out the value from the channel; However, the channel can also be limited to only sending operations(send-only)Or only receive operations can be performed(receive-only )。

Usually it can be calledDirectional channel, some people callUnidirectional channelIn fact, both of them point to the discussion in this essayDirectional Channel

The following is a direct example:

package onlyChannelTest

import (
	"fmt"
	"math/rand"
	"sync"
	"testing"
	"time"
)

func TestOnlyChannel(t *testing.T) {
	var wg sync.WaitGroup
	wg.Add(2)

	c:= make(chan int, 3)
	var send chan<- int = c
	var recv <-chan int = c

	go func() {
		defer wg.Done()
		for i := 0;  i < 6;  I + + {// note that here is 6
			fmt.Print("receive\n")
			fmt.Println(<-recv)
		}
	}()

	go func() {
		defer wg.Done()
		defer close(c)

		rand.Seed(time.Now().UTC().UnixNano())
		for i := 0;  i < 3;  I + + {// here is 3
			fmt.Print("send\n")
			send <- rand.Intn(100)
		}
	}()

	wg.Wait()
}

Here, you can guess the running results first. I’ll post it directly:

The following caught my attention:

receive
0

Is the most confusing place for me, because in the general impressionchannelAre blocking, and from the above results, the first onerecvIt’s also blocked). But in the backrecvBut did not play a blocking role, orcDefault values in0Output.

adoptdebug, it is not difficult to see that the sending and receiving of the two one-way channels are operated from one buffer channel, and the two single channels belong to the same two-way channel, but they are limited to the receiving and sending functions respectively.

adoptdebug, again, inrecvAfter reading, the channel is not blocked“Empty”, but keep the default value.

Do you?recvNot blocked?

The verification method is as follows:


// defer close(c)

Select comment out sendGoroutineClose the channel in the.

The result is obvious, causing deadlock, which proves that there is communication and blocking between two one-way channels.

Finally, we found the answer through the source code:

Thus, in order to avoid receiving unnecessary invalid messagesZero value, the receipt shall be modifiedGoroutinereceiveHow to write:

go func() {
		defer wg.Done()
		for i := 0;  i < 6;  I + + {// note that here is 6
			x, ok := <-recv
			if ok {
				fmt.Print("receive\n")
				fmt.Println(x)
			}else{
				break
			}
		}
	}()

 

This is the end of this article about golang’s implementation of directional channel. For more information about golang’s directional channel, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!