Go 语言基础 - channels ( 通道 ) ( 二 )

yufei       6 年, 3 月 前       854

Go 语言基础 - channels ( 通道 ) ( 一 ) 中我们讲解了 Go 语言 channel 的一些基本使用。本章节我们就来探索一些高级的知识

channel 类型

将一个 channel 类型作为一个函数的参数或返回值时,channel 操作符采用的则是另一种表现,也就是

channel 类型仅仅定义了单向信道,即 「 仅接收 」 和 「 仅发送 」 channel

仅接收 channel

下面的代码声明了一个仅用于接收值的 channel

arg <- chan int 

仅发送 channel

下面的代码则声明了一个仅用于发送值的 channel

arg chan <- int

这个语法有点另类,也有点难记,因为把 chanint 拆开了

范例

package main

func getRcvOnlyChan() <- chan int {
    return make(chan int)
}

func main() {
    c := getRcvOnlyChan()
    c <- 1
}

运行结果如下

$ go run demo.go
# command-line-arguments
./demo.go:9:4: invalid operation: c <- 1 (send to receive-only type <-chan int)

陷阱

  • 单向 channel 无法转换回双向 channel

特征

「 不缓冲 」 和 「 零缓冲 」 channel

「 不缓冲 」 和 「 零缓冲 」 channel 在仅在发送方和接收方之间同步发送一个类型的值,换句话说,发送值会阻止发送方的执行,直到接收方准备好读取该值,同样的,接收值会阻止接收方的执行,直到发送者准备发送值为止。值的传输方式: 值直接复制到接收器的堆栈

「 可缓冲 」 channel

一个 「 可缓冲 」 channel 会在发送器和接收器之间传输一个类型的值,采用一下两种方式之一

  • 异步,如果缓冲区有剩余的可用空间
  • 同步,如果缓冲区已满了,此时会发生阻塞

「 空值 」 channel

往 「 空值 」 channel 发送值或接收值会无限期的阻塞操作

这种行为看起来有用 ?

是的。

一般用于 select 语句中。

一般情况下,当需要等待可用的 channel 的情况下,可以使用一个 「 已关闭 」channel 来无限期的阻塞,直到可用 channel 可用为止。当然了,它也有副作用,就是浪费了不少时间从 「 已关闭 」channel 来读取 零值 ,但如果使用 「 空值 」channel,从 「 空值 」channel 通道转换到 可用 channel 时则不会发生这种情况

select channel

正如我们所发现的那样,由于 channel 的性质或者队列已满,channel 操作可能会阻塞。那么我们要如何编写在一对多 channel 上运行的 goroutine ,而不会一直看到特定 channel 停止执行

这种时候,select 语句就派上用场了,此语句将阻塞,直到其分支中的至少一个可以执行,如果多个分支有资格执行,则以非确定性方式随机挑选一个分支

要终止从其某个分支执行语句,请使用 break 语句

范例

package main

import "fmt"

func main() {
    a := make(chan int)
    b := make(chan int)

    go func() {
        select {
        case val := <-a:
            fmt.Println("Received from a:", val)
        case val := <-b:
            fmt.Println("Received from b:", val)
        }
    }()

    b <- 520
}

运行结果如下

$ go run demo.go
Received from b: 0

出现输出 Received from b: 0 是概率事件,因为这种情况下,其实两个通道都可用,所以会随机选择一个

最佳实战

因为在循环中包含 channel select 是很常见的,请记住使用 break 终止执行最里面的 forselectswitch 语句

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.