zoukankan      html  css  js  c++  java
  • channel

    channel

    Go语言在语言级别提供的goroutine间的通信方式,让他们之间可以进行数据交互。

    声明方式:

    var chanName chan ElementType
    
    // 如:
    var ch1 chan int
    // 也可以使用make函数创建
    ch2 := make(chan string)
    

    上面创建了两个channel,ch1只能用来存储int类型的数据,ch2只能用来存储string类型的数据。

    channel的写与读

    channel的写与读也非常简单,使用<-符号实现,<-在channel变量名右边表示写入值,<-在左边表示读取值。

    如:

    ch := make(chan int)
    ch <- 10      // 向ch中写入10
    res := <-ch   // 读取ch中的值并赋值给res
    

    案例:

    package main
    
    import (
    	"fmt"
        "time"
        "strconv"
    )
    
    func Read(ch chan int){
        for {
            value := <-ch
        	fmt.Println("value:" + strconv.Itoa(value))
        }
    }
    func Write(ch chan int){
        ch <- 10 
    }
    
    func main(){
        ch := make(chan int)
        
        go Read(ch)
        go Write(ch)
        time.Sleep(10)
    }
    

    输出:

    value:10
    

    上面的代码中分别有两个函数,函数Read用来从channel中读取值,函数Write用来往channel里面写值,注意value := <-ch在读取值时可能存在channel中无数据存在的情况,如果没有数据可读就会阻塞,直到从channel中读取到数据。因为会不断从channel中读取可能存在的数据,所以一般都会使用一个死循环来读取channel数据,避免写入channel中的数据会丢失。

    channel的操作

    channel都有3中操作:send、receive和close

    • send:表示向channel中投放数据
    • receive:表示从channel中读取数据
    • close:表示关闭channel

    注意:

    • 关闭channel后,send操作将导致painc(抛出异常)。
    • 关闭channle后,receive操作将返回对应类型的0值以及一个状态码false。
    • close并非强制需要使用,在某些时候可以自动被关闭。
    • 如果使用了close(). 建议条件允许的情况下加上defer
    • 只在send端上显式使用close()关闭channel。因为关闭通道意味着没有数据需要发送。

    案例,判断channel是否被关闭:

    val, ok := <-ch
    if ok{
        fmt.Println(val)
    }
    

    缓冲channel

    在对channel写入数据后,如果没有读取的操作,程序就会阻塞着不运行,这个时候我们想要程序不阻塞,就可以设置一个缓冲区大小,如果写入值数量超过缓冲区大小时再进行阻塞,声明channel时,可以再跟一个参数,代表缓冲区大小。

    声明,如:

    c := make(chan int, n)  // n代表缓冲区大小
    
    c := make(chan int)  // 没写参数,代表0 等价于c := make(chan int, 0)
    

    案例:

    func test(ch chan int){
        ch <- 10
        fmt.Println("come to goroutine")
    }
    
    func main(){
        ch := make(chan int)
        go test(ch)
        time.Sleep(time.Second * 3)
        fmt.Println("runing end")
    }
    

    输出结果为:

    runing end
    

    因为创建的channel没有设置缓冲区大小,而且在写入值之后也没有读取值的操作,所以程序阻塞,没有打印"come to goroutine"。

    修改缓冲区大小,如:

    func test(ch chan int){
        ch <- 10
        fmt.Println("come to goroutine")
    }
    
    func main(){
        ch := make(chan int,1)
        go test(ch)
        time.Sleep(time.Second * 3)
        fmt.Println("runing end")
    }
    

    输出结果为:

    come to goroutine
    runing end
    
  • 相关阅读:
    ActiveMQ消息队列技术融合Spring
    ActiveMQ消息队列技术Demo
    网页静态化技术Freemaker
    Solr的基本语法
    Solr的页面展示以及高亮显示
    Solr的了解与配置
    Angular中上传图片到分布式文件服务器FastDFS上
    分布式文件服务器FastDFS的使用
    自我学习笔记01
    数组转换成List集合
  • 原文地址:https://www.cnblogs.com/louyefeng/p/11367766.html
Copyright © 2011-2022 走看看