channel 是go语言中不同goroutine之间通信一种方法
//定义一个channel
c := make(chan bool)
//向channel中写入
c <- true
//读取channel
<-c
有缓存,写入或者读出后继续往下执行;
在读的地方,如果别的地方没有写入,则阻塞在那,等有写入时才,读出,继续执行下去;
在写的地方,如果别的地方没有读就会阻塞在写的这个地方,等带别的地方读出来;不被读掉就会阻塞;
无缓存通道只有读写同时发生是才不阻塞;
向一个通道中读或者写时,必须要有别的携程接受了这个参数;
取在读前面.有缓存是异步,无缓存是同步阻塞;
package main
import (
"log"
"sync"
//"time" //延迟用
)
//channel 是一个引用类型
func main() {
//demo1()
//demo3()
//demo4()
//demo5()
demo6()
}
//简单的迭代操作
func demo1(){
c := make(chan bool) //双向通道
go func(){
log.Println("gogogo!")
c <- true //向channel c中输入
close(c) //当channel在迭代操作是,必须在某个地方关闭它,不然程序将会进入死锁
}()
//go Go() //并发执行
//time.Sleep(2 *time.Second) // 延迟两秒中
//<-c //阻塞中只有当并发执行的方法中向c中输入是这边才继续往下执行
for v := range c{ //迭代操作c
log.Println(v)
}
}
func Go() {
log.Println("gogogo!")
}
//单向通道
func demo2() {
}
//缓存:取在读前面.有缓存是异步,无缓存是同步阻塞;
//有缓存:有缓存,就会写入或者读出后继续往下执行;无缓存通道只有读写同时发生是才不阻塞;向一个通道中读或者写时,必须要有别的携程接受了这个参数;
//无缓存:在读的地方,如果别的地方没有写入,则阻塞在那,等有写入时才,读出,继续执行下去;在写的地方,如果别的地方没有读就会阻塞在写的这个地方,等带别的地方读出来;不被读掉就会阻塞;
func demo3(){
//c := make(chan bool,1) //有缓存
c := make(chan bool) //无缓存
go func(){
log.Println("123")
c <- true //写入
}()
<- c //读出
}
func demo4() {
c := make(chan bool,10) //定义缓存为10
for i:=0;i< 10;i++ {
go demo4Go(c,i)
}
for i:=0;i<10;i++ { //循环读出10次后结束
<-c
}
}
func demo4Go(c chan bool,index int){
a := 1
for i := 0; i<1000000; i++ {
a += i
}
log.Println(index,a)
c <- true //循环一次向channel中写一次
}
//创建任务组。WaitGrpup,并发执行,使用WaitGroup实现所有进程都完成
func demo5() {
wg := sync.WaitGroup{}
wg.Add(10) //添加十个任务
for i:=0;i< 10;i++ {
go demo5Go(&wg,i) //wg传递为地址传递
}
wg.Wait() //当全部任务完成后 继续执行
}
func demo5Go(wg *sync.WaitGroup,index int){
a := 1
for i := 0; i<1000000; i++ {
a += i
}
log.Println(index,a)
wg.Done() //干掉一个任务
}
func demo6(){
c1,c2 := make(chan int),make(chan string) //定义两个channel
o := make(chan bool) //总channel
go func(){
for {
select {
case v,ok := <- c1:
if !ok {
o<-true
break
}
log.Println("c1",v)
case v,ok := <-c2:
if !ok {
o<-true
break
}
log.Println("c2",v)
}
}
}()
c1 <- 1
c2 <- "hello"
c1 <- 2
c2 <- "world"
close(c1)
close(c2)
<- o
}