• (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方法结束")
    }
  • 相关阅读:
    精选微软经典的算法面试100题
    C++高效程序设计
    算法导论第五章:概率分析和随机算法
    算法导论第六章:堆排序
    算法导论第八章:线性时间排序
    算法导论第六章:堆排序
    算法导论第七章:快速排序
    M0n0wall安装及配置教程(上)
    ASP.NET十分有用的页面间传值方法
    PC网络配置切换脚本(IP地址切换脚本)
  • 原文地址:https://www.cnblogs.com/buchizaodian/p/10798032.html
Copyright © 2020-2023  润新知