• GO Channel


    1 不缓存的channel

    以最简单方式调用make函数创建的时一个无缓存的channel,但是我们也可以指定第二个整形参数,对应channel的容量。如果channel的容量大于零,那么该channel就是带缓存的channel

    ch = make(chan int)    // unbuffered channel
    ch = make(chan int, 0) // unbuffered channel

    一个基于无缓存Channels的发送操作将导致发送者goroutine阻塞,直到另一个goroutine在相同的Channels上执行接收操作,当发送的值通过Channels成功传输之后,两个goroutine可以继续执行后面的语句。
    反之,如果接收操作先发生,那么接收者goroutine也将阻塞,
    直到有另一个goroutine在相同的Channels上执行发送操作

    func gosum(s []int, c chan int) {
        sum := 0
    
    
        for _, v := range s {
            sum += v
        }
        c <- sum // send sum to c
    }

        var si []int = []int{1, 2, 3, 4}
        chan_c := make(chan int, 0)
    
    
        go gosum(si, chan_c)
    
    
        rs := <-chan_c
    
    
        fmt.Println(rs)
     

    2 缓存的channel

    带缓存的Channel内部持有一个元素队列。通过缓存的使用,可以尽量避免阻塞,提供应用的性能。队列的最大容量是在调用make函数创建channel时通过第二个参数指定的,比如

    ch = make(chan int, 3) // buffered channel with capacity 3
    我们可以在无阻塞的情况下连续向新创建的channel发送三个值
    ch <- "A"
    ch <- "B"
    ch <- "C"
    此刻,channel的内部缓存队列将是满的,如果有第四个发送操作将发生阻塞。channel的缓存队列解耦了接收和发送的goroutine

    3 channel & Range

        c := make(chan int)
        go func() {
            for i := 0; i < 10; i = i + 1 {
                c <- i
                time.Sleep(1 * time.Second)
            }
            close(c)
        }()
    
    
        for i := range c {
            fmt.Println(i)
        }
    
    
        time.Sleep(100 * time.Second)

    range c 产生的迭代值为Channel中发送的值,它会一直迭代知道channel被关闭。上面的例子中如果把 close(c) 注释掉,程序会一直阻塞在 for …… range 那一行
     

    4 单向channel

    Go语言的类型系统提供了单方向的channel类型,分别用于只发送或只接收的channel。类型chan<- int表示一个只发送int的channel,只能发送不能接收。相反,类型<-chan int表示一个只接收int的channel,只能接收不能发送。(箭头<-和关键字chan的相对位置表明了channel的方向。)这种限制将在编译期检测。

    因为关闭操作只用于断言不再向channel发送新的数据,所以只有在发送者所在的goroutine才会调用close函数,因此对一个只接收的channel调用close将是一个编译错误

    func gosum(s []int, c chan<- int) {
        sum := 0
    
    
        for _, v := range s {
            sum += v
        }
        c <- sum // send sum to c
    }

    5 channel&goroutines应用-批量查询数据库

    func Query(conns []Conn, query string) Result {
        ch := make(chan Result, len(conns))  // buffered
        for _, conn := range conns {
            go func(c Conn) {
                ch <- c.DoQuery(query):
            }(conn)
        }
        return <-ch
    }
     

    6 select

    select 语句选择一组可能的send操作和receive操作去处理。它类似 switch ,但是只是用来处理通讯(communication)操作。它的 case 可以是send语句,也可以是receive语句,亦或者 default 。receive 语句可以将值赋值给一个或者两个变量。它必须是一个receive操作。最多允许有一个 default case ,它可以放在case列表的任何位置,尽管我们大部分会将它放在最后。

    如果有同时多个case去处理,比如同时有多个channel可以接收数据,那么Go会伪随机的选择一个case处理(pseudo-random)。如果没有case需要处理,则会选择 default 去处理,如果 default case 存在的情况下。如果没有 default case ,则 select 语句会阻塞,直到某个case需要处理

    select 语句和 switch 语句一样,它不是循环,它只会选择一个case来处理,如果想一直处理channel,你可以在外面加一个无限的for循环

  • 相关阅读:
    Session的使用与管理
    CSS控制文字,超出部分显示省略号
    MP4 文件前端获取视频封面
    prefetch预加载功能使用
    react-学习之路-react-router-解决问题记录
    如何将一个div盒子水平垂直都居中?
    window下查看端口号,并删除对应进程
    判断js 验证字符串里面有没有包含汉字:
    vue 现有的$变量 以及如何添加全局变量
    与人言
  • 原文地址:https://www.cnblogs.com/sysnap/p/6894506.html
Copyright © 2020-2023  润新知