(17) go 协程管道

 一、协程

 

查看CPU数目

import (
    "fmt"
    "runtime"
)

func main() {
    num := runtime.NumCPU()
    fmt.Print(num)
}

 

 二、管道

管道用来在多个协程间进行通信

 初始化分配

    //使用make的类型 slice map chan
    //存放int类型的通道
    //这种定义方式只定义,未分配内存的(未初始化)
    var ch1 chan int
    //初始化并分配内存
    ch2:=make(chan int)
    //存进通道
    ch2<-3
    //从通道中取出
    ret2:=<-ch2
    //直接打印报错了---fatal error: all goroutines are asleep - deadlock!
    print(ret2)

 开辟容量

    //如果想要使用,需要加容量
    ch3:=make(chan int,1)
    ch3<-108
    ret3:=<-ch3
    print(ret3)

不能存放超过通道容量的数量

    ch3:=make(chan int,1)
    ch3<-108
    //定义了一个容量,确试图存放第二个数据进去
    //报-fatal error: all goroutines are asleep - deadlock!
    ch3<-99

取出的数量超过通道内存放的数量报错

    ch3:=make(chan int,1)
    ch3<-108
    ret3:=<-ch3
    //只有一个容量,确想要存放两个数据进去
    //报错--fatal error: all goroutines are asleep - deadlock!
    ret4:=<-ch3
    print(ret3)
    print(ret4)

取出超过通道内存放的数量就会报错,不管你开辟的多大的通道空间

    ch:=make(chan int,100)
    ch<-108
    ch<-88
    ret1:=<-ch
    ret2:=<-ch
    //fatal error: all goroutines are asleep - deadlock!
    ret3:=<-ch
    println(ret1)
    println(ret2)
    println(ret3)

 关闭通道

    ch:=make(chan int,100)
    ch<-108
    ch<-88
    ret1:=<-ch
    println(ret1)
    //关闭通道
    close(ch)
    //可以取出数据
    ret2:=<-ch
    println(ret2)
    //如果取出的数据超过了存放的数量,
    //不会报错,取出的值是该类型的默认值,例如存放int的通道取出的值为0
    ret3:=<-ch
    println(ret3)
    //关闭了的通道不允许再存放值
    //报错--panic: send on closed channel
    ch<-99

 

    ch:=make(chan int,100)
    ch<-108
    ret1:=<-ch
    println(ret1)
    //关闭通道
    close(ch)
    //关闭一个已经关闭的通道会报错
    //panic: close of closed channel
    close(ch)

 通道数量与容量

    ch:=make(chan int,10)
    ch<-88
    //通道中元素的数量
    println(len(ch))//1
    <-ch
    println(len(ch))//0
    //通道总容量
    println(cap(ch))//10

 判断通道关闭

func main() {
    ch:=make(chan int,10)
    go test(ch)
    //编译一个未关闭的通道报错,fatal error: all goroutines are asleep - deadlock!
    //遍历一个关闭的通道,可以正常向下执行
    for ch :=range ch{
        println(ch)
    }
    println("main  end")
}

func test(ch chan int)  {
    for i:=0;i<10;i++ {
        ch<-i
    }
    //close(ch)
}

或者使用for 循环

    for{
        ret,ok:=<-ch
        if !ok{
            break
        }
        println(ret)
    }

 

 

无缓冲通道

chan不开辟容量

无缓冲通道必须要保证,往通道存放的时候,程序必须也正在向外取该通道的数据

package main

func main() {
    ch:=make(chan int)
    //
    go test(ch)
    ch<-10
    println("main方法结束")
}

//有可能这个方法还没执行完,主程序就结束了。
func test(ch chan int)  {
    println("test方法开始")
    //如果ch没有数据,则阻塞到当前位置
    //有数据时向下执行
    ret:= <-ch
    println(ret)
    println("test方法结束")
}

 

有缓冲通道

 ?????

func main() {
    ch:=make(chan int,10)
    //
    ch<-99

    go test(ch)
    ch<-88
    time.Sleep(1000)
    println("main方法结束")
}

//有可能这个方法还没执行完,主程序就结束了。
func test(ch chan int)  {
    //println("test方法开始")
    //如果ch没有数据,则阻塞到当前位置
    //有数据时向下执行
    ret:= <-ch
    println(ret)
    println("test方法结束")
}

 

posted @ 2019-04-30 20:43  富坚老贼  阅读(183)  评论(0编辑  收藏  举报