Go study notes - channel
1. Channel
channel
It 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 channel
is:
make(chan val-type)
-
make
The function description for channel is: use the specified buffer capacity to initialize the buffer of the channel. -
chan
Is the keyword, representativechannel
. -
val-type
Is 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 <-channel
receive 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 true
indicates 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 <-chan
as 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 pings
through 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 pings
the data in the channel, and then transfer it pongs
to 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 select
is:
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.