Go study notes - channel

Go study notes - channel


1. Channel

channelIt is a pipe connecting multiple gotoutine. It is possible to send values ​​to a pipe from one goroutine and receive them in another goroutine.

The syntax for creating channelis:

make(chan val-type)
  • makeThe function description for channel is: use the specified buffer capacity to initialize the buffer of the channel.

  • chanIs the keyword, representative channel.

  • val-typeIs the type, representing what type of data the channel accepts.

<-Is the channel operator, referring to the direction of data flow. Use channel<-to send a new value to the channel. Use to <-channelreceive a new data from the channel.

messages <- msg
//messages是通道名,将msg发送到通道messages中

msg <- messages
//用msg来接收从通道messages中传来的数据

Define a channel to transmit data, and use a variable to receive the transmitted data.

func main(){
    
    

	//定义一个channel通道
	messages := make(chan string)

	//将一个函数放在协程中运行,并用通道传输数据
	go func() {
    
    messages <- "ping"}()

	//接收通道传输的信息
	msg := <-messages
	fmt.Println(msg)
}

//ping

Through examples, it can be seen that messages “ping”are sent from one Go coroutine to another through channels.

By default, both send and receive operations block until the other end is ready.

func sum(s []int,c chan int){
    
    
	sum := 0
	for _,v := range s{
    
    
		sum += v
	}
	c <- sum  //将和送入C
}

func main(){
    
    
	s := []int{
    
    7,2,4,5,8,1}

	c := make(chan int)
	go sum(s[:len(s)/2],c)
	go sum(s[len(s)/2:],c)

	x,y := <-c,<-c   //x,y从C中接受数据
	fmt.Println(x,y,x+y)
}

2. Channel buffering

When creating a channel, the default is unbuffered. Therefore, a send is only allowed if the corresponding receive channel is ready to receive.

Bufferable channels allow a limited number of values ​​to be buffered without a corresponding receiver.

When the channel has a buffer, the operation of the channel is guaranteed without a corresponding concurrent receiver.

func main(){
    
    

	//定义一个channel,设置缓冲区为2
	messages := make(chan string,2)

	//通过goroutine传递信息
	//go func() {messages <- "ping"}()
	messages <- "buffered"
	messages <- "channel"

	//接收通道传输的信息
	msg := <-messages
	fmt.Println(msg)
    
    //直接输出通道接收的数据
	fmt.Println(<-messages)
}

//buffered
//channel

3. Channel synchronization

Use channels to synchronize execution state between Go goroutines.

func worker(done chan bool){
    
    
	fmt.Println("working")
	//模拟阻塞
	time.Sleep(time.Second)
	fmt.Println("done")

	done <- true
}

This is a function that will be executed in a Go goroutine, and the done channel will be used to notify other Go goroutines that this function has finished working. Send trueindicates that the channel has finished running.

func main(){
    
    
    done := make(chan bool,1)
    go worker(done)
    
    <-done
}

The program will block until it receives a notification from a worker in the channel.

4. Channel direction

When using a channel as a function parameter, you can specify whether the channel is only used to send or receive values.

Using a channel as a parameter allows only sending chan<-or receiving <-chanas a parameter depending on the direction of the data flow.

Define a ping()function whose parameter is a channel that only allows sending data.

func ping(pings chan<- string,msg string){
    
    
    pings <- msg
}

Define a pong()function whose parameters can be used to receive data or send data.

func pong(pings <-chan string,pongs chan<- string){
    
    
    msg := <-pings
    pongs <- msg
}

After the main function is called, the output data is ping()transmitted to the channel pingsthrough the function. Since ping()the function cannot be used to receive data, but the output data still exists in the channel, then call pong()the function to obtain pingsthe data in the channel, and then transfer it pongsto the channel. output.

func main(){
    
    
	pings := make(chan string,1)
	pongs := make(chan string,1)
	//调用ping函数发送数据到msg中
	ping(pings,"passed message")
	//调用pong函数
	pong(pings,pongs)
	fmt.Println(<-pongs)
}

//passed message

5. Channel selector

The channel selector in Go language can wait for multiple channel operations at the same time.

The syntax for a channel selector selectis:

select{
    
    
    case handle1 :
    	statement
    case handle2 :
    	statement
}

//handle1和handle2是在case中做的处理或者判断
//statement是在符合条件后需要执行何种语句

Define two channels and output the values ​​in the channels.

func main(){
    
    
	c1 := make(chan string)
	c2 := make(chan string)

	go func(){
    
    
        //通过时间来模拟阻塞
		time.Sleep(time.Second * 4)
		c1 <- "one"
	}()

	go func() {
    
    
        //通过时间来模拟阻塞
		time.Sleep(time.Second * 1)
		c2 <- "two"
	}()

	for i:=0;i<2;i++{
    
    
		//选择通道的运行
        select {
    
    
		case msg1 := <-c1:
			fmt.Println("received",msg1)
		case msg2 := <-c2:
			fmt.Println("received",msg2)
		}
	}
}

//received two
//received one

It can be seen from the example that in the parallel coroutines, the selector will choose the coroutine that unblocks first to run.

Guess you like

Origin blog.csdn.net/weixin_46435420/article/details/119647414