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
    
  • 相关阅读:
    组装query,query汇总,query字段
    POJ 1276, Cash Machine
    POJ 1129, Channel Allocation
    POJ 2531, Network Saboteur
    POJ 1837, Balance
    POJ 3278, Catch That Cow
    POJ 2676, Sudoku
    POJ 3126, Prime Path
    POJ 3414, Pots
    POJ 1426, Find The Multiple
  • 原文地址:https://www.cnblogs.com/louyefeng/p/11367766.html
Copyright © 2011-2022 走看看