channel 作用:相当于rpc,进程间通信,或者类似于socket。
1.图解+定义+同步(阻塞)-异步
2.无缓冲
3.有缓冲
4.关闭
5.select
1.图解+定义
同步(阻塞):
main 先到,就会停那等sub值,
sub 先到,也会停那等main值。
语法:
make(chan Type) 等价于 make(chan Type,0)
make(chan Type,capacity)
channel <- value //发送 value 到 channel
<- channel // 接收并将其丢弃
x:=<- channel // 从 channel中接收数据,并赋值给x
x,ok:=<- channel // 功能同上,检查通道是否已关,是否为空
package main
import "fmt"
func main(){
c:=make(chan int) //1.创建一个管道 c
go func(){
defer fmt.Println("goroutine结束")
fmt.Println("goroutine 正在运行....")
c <-666 //2.发:函数里 将666 发送给c
}()
num:=<-c //3.收:从C中接受数据,并赋值给num
fmt.Println("num= ",num)
fmt.Println("main goroutine 结束 ")
}
2.无缓冲
代码:
3.有缓冲
代码:
有缓存不会发生阻塞。
package main
func main(){
c:=make(chan int,3) //1.带有缓冲的channel
fmt.Println("len(c)",len(c),",cap(c)",cap(c))
go func(){ //2.发送
defer fmt.Println("子go结束")
for i:=0;i<3;i++{
c <- i
fmt.Println("子go 发送=",i,"len(c)=",len(c),",cap(c)=",cap(c))
}()
time.Sleep(2*time.Second)
for i:=0;i<3;i++{ //3.接收
num := <-c
fmt.Println("num=",num)
}
fmt.Println("main 结束")
}
当发送数>管道数时就会阻塞的。
4.关闭
写不关的,读会陷入死循环。
关之后不可以写,但可以读,直到没有数据为止。
package main
func main(){
c:=make(chan int)
go func(){ // 1.写: sub channel里写i
for i:=0;i<5;i++{
c<-i
}
close(c) //关闭 channel
}()
for{ //2.读:
// ok如果为true表示channel 没有关闭,如果为false 表示channel 已经关闭
if data,ok := <-c ; ok{ //channel 没关
fmt.Println(data)
}else{
break // channel 关闭
}
}
/*
for data:=range c{
fmt.Println(data)
}
*/
fmt.Println("main finished...")
}
5.select
多个channel的情况:
select{
case <- chanl: //如果chan1读到数据
case chan2 <-1: //如果向chan2写数据
default: //如果上面都没有成功
}
package main
import(
)
func fibonacii(c,quit chan int){ //两个channel
x,y :=1,1
for{
select {
case c<-x: //1.c可写
x=y
y=x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main(){
c:=make(chan int)
quit :=make(chan int)
//sub go
go func(){
for i:=0;i<6;i++{
fmt.Println(<-c) //2.线程c 读c
}
quit <-0 //3.线程quit 写0
}()
//main go
fibonacii(c,quit)
}