zoukankan      html  css  js  c++  java
  • 信道

    什么是信道?

    信道可以想像成 Go 协程之间通信的管道。如同管道中的水会从一端流到另一端,通过使用信道,数据也可以从一端发送,在另一端接收。

    信道的声明

    所有信道都关联了一个类型。信道只能运输这种类型的数据,而运输其他类型的数据都是非法的。

    chan T 表示 T 类型的信道。
    
    信道的零值为 nil。信道的零值没有什么用,应该像对 map 和切片所做的那样,用 make 来定义信道。

    信道的发送和接收

    a <- 1  //表示在a里面放入1
    b := <-a  //将a值取出来,赋值给b

    发送和接收默认是阻塞的

    当把数据发送到信道时,程序控制会在发送数据的语句处发生阻塞,直到有其它 Go 协程从信道读取到数据,才会解除阻塞。与此类似,当读取信道的数据时,如果没有其它的协程把数据写入到这个信道,那么读取过程就会一直阻塞着。

    代码示例

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func test(a chan int){
        fmt.Println("你好啊!")
        //放值
        time.Sleep(time.Second*3)  //睡三秒后再打印b值
        a <- 1  //表示在a里面放入1
    }
    func main(){
        var a chan int = make(chan int)  //注意:一定要初始化
        go test(a)
        b := <-a  //将a值取出来,赋值给b
    
        fmt.Println(b)
    
    
    }

    死锁

    默认取值和赋值都是阻塞的。当 Go 协程给一个信道发送数据时,照理说会有其他 Go 协程来接收数据。如果没有的话,程序就会在运行时触发 panic,形成死锁。

    同理,当有 Go 协程等着从一个信道接收数据时,我们期望其他的 Go 协程会向该信道写入数据,要不然程序就会触发 panic。

    package main
    
    func main() {  
        a := make(chan int)
        a <- 5
    }

    单向信道

    func sendData(sendch chan<- int) {  // chan<- int 是只写的,如果读取信道就会报错
        sendch <- 10
    
    }
    
    func main() {
        // 只写信道
        sendch := make(chan int)
        go sendData(sendch)
        fmt.Println(<-sendch)
    }

    信道关闭

    数据发送方可以关闭信道,通知接收方这个信道不再有数据发送过来。

    当从信道接收数据时,接收方可以多用一个变量来检查信道是否已经关闭。

    package main
    
    import (
        "fmt"
    )
    
    func producer(chnl chan int) {
        for i := 0; i < 10; i++ {
            chnl <- i
        }
        close(chnl)
    }
    func main() {
        ch := make(chan int)
        go producer(ch)
        for {
            v, ok := <-ch
            // 如果信道关闭,ok就是false
            // 如果没关闭,就是true
            if ok == false {
                break
            }
            fmt.Println("Received ", v, ok)
        }
    }

    通过range循环信道

    func producer(chnl chan int) {
        for i := 0; i < 10; i++ {
            chnl <- i
        }
        close(chnl)
    }
    func main() {
        ch := make(chan int)
        go producer(ch)
        for v := range ch {
            fmt.Println("Received ",v)
        }
    }
  • 相关阅读:
    [][]
    Spark笔记04
    Spark笔记03
    Spark笔记02
    Spark笔记01
    【熟能生巧】使用Screw快速生成数据库文档
    记一次关于jdbcTemplate.queryForList快速Debug及感悟
    【从零单排】Exception实战总结1
    【从零单排】Java性能排查实战模拟
    【从零单排】关于泛型Generic的一些思考
  • 原文地址:https://www.cnblogs.com/xiongying4/p/12037037.html
Copyright © 2011-2022 走看看