首页 > 其他分享 >Golang中的Channel(二)

Golang中的Channel(二)

时间:2023-07-07 15:33:47浏览次数:33  
标签:case ch ok Golang Channel channel close select

上篇介绍了Channel是什么以及它的类型,这篇总结一下Channel的用法。

 

  1. 基本语法

(1)        声明channel

声明channel的语法格式为:

var ChannelName chan ElementType

与其他变量声明不同的是,在类型前面多了一个chan关键字。ElementType指的是这个channel能够传递的数据类型。

在golang中需要使用内置的make函数类创建channel的实例:

ch := make(chan int) //声明并初始化了一个名为ch的int型channel

 

(2)        发送接收数据

ch -< value //向channel中发送数据

【send操作注意】:

a)   c -< 3+4 //先求值再传递

b)   往一个已经被close掉的channel中发送数据会导致run-time panic

c)   注意channel是否有缓存。无缓存的channel只有在receiver准备好后send才能被执行。有缓存且缓存未满,send可以直接被执行。

value := <- ch //将channel中的数据读取到变量中

【receive操作注意】:

a)   从一个被close的channel中取数据不会被阻塞,而是立即返回,接收完已发送的数据会返回元素类型的零值。可以用一个额外的返回参数来检查channel是否关闭:

x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch

如果ok是false,表示接收的x是产生的零值,这个channel被关闭了或者为空。

 

(3)        Select

在linux系统中,select函数用来监控一系列的文件句柄,一旦有文件句柄发生了I/O动作,select函数就会返回,主要被用来实现高并发的socket服务器程序。

Golang中,select关键字和linux的select函数功能相似,主要用于处理I/O异步问题。

select的语法与switch相似,由select开始一个新的选择块,每个选择条件由case语句来描述。

与switch语句相比,select有比较多的限制,其中最大的一条限制就是每个case语句必须是一个I/O操作。

        大致结构:

                select {

                case <-chan1:   //如果 chan1 成功读取到数据,则执行该 case                    

                case chan2 <- 1://如果成功向 chan2 写入数据,则执行该 case            

                default:   // 如果上面的条件都没有成功,则执行 default 流程

                }

可以看出,select 不像 switch,后面并没有条件判断,而是直接去查看 case 语句。每个 case 语句都必须是一个面向 channel 的操作。

 

  1. channel的遍历

for …… range语句可以遍历channel。但是它会一直迭代直至channel被关闭。

 

图中例子,如果把close(c)注释掉,程序会一直阻塞在for…range那行。

再看一个例子:

 

这段代码可以正常执行。

 

换成这段代码,会出现fatal error: all goroutines are asleep - deadlock!

总之,for…range是阻塞式读取channel,只有channel close后才会结束。

 

  1. 处理超时

在使用channel的时候要小心,比如

i := <= ch

当碰到永远没有往ch中写入数据的情况,那么这个读取就永远无法成功。导致的结果就是整个goroutine永远阻塞并且没有挽回的机会。

Golang没有提供直接的超时处理机制。可以利用select机制来解决,因为select的特点是只要其中一个case满足,程序就会继续往下执行,而不会考虑其他的case。基于此特性,可以实现一个channel的超时机制:

ch := make(chan int)

// 首先实现并执行一个匿名的超时等待函数

timeout := make(chan bool, 1)

go func() {

    time.Sleep(1e9) // 等待 1 

    timeout <- true

}()

// 然后把 timeout 这个 channel 利用起来

select {

    case <-ch:

    //  ch 中读取到数据

    case <- timeout:

    // 一直没有从 ch 中读取到数据,但从 timeout 中读取到了数据

    fmt.Println("Timeout occurred.")

}

执行上述代码,输出结果为:

          Timeout occurred.
  1. 关闭channel

内建的close方法可以用来关闭channel:

        close(ch)

判断一个channel是否已关闭,可以增加一个布尔类型的值:

        x, ok := <-ch

如果ok的值为false,就表示已经被关闭。

标签:case,ch,ok,Golang,Channel,channel,close,select
From: https://www.cnblogs.com/gongxianjin/p/17535125.html

相关文章

  • Golang中的Channel(一)
    Golang在并发编程上有两大利器,分别是channel和goroutine。Golang中有一句名言:“使用通信来共享内存,而不是通过共享内存来通信”。这句话有两层意思,Go语言确实在sync包中提供了传统的锁机制,但更推荐使用channel来解决并发问题。这里先对Channel做一个基本的介绍,对于其深一层的实现......
  • Golang的类图
    @目录1.依赖(Dependency)1.1概念1.2代码示例1.3类图示例2.泛化(Generalization)-继承2.1概念2.2代码示例2.3类图3.泛化(Generalization)-实现3.1概念3.2代码示例3.3类图4.关联关系(Association)4.1概念4.2代码示例4.3类图5.聚合关系(Aggregation)5.1概念5.2代码示例5.3......
  • golang 解析yaml文件
    初始化packagemainimport( "github.com/spf13/viper")funcinitConfig(){ viper.SetConfigName("config") viper.AddConfigPath("./") iferr:=viper.ReadInConfig();err!=nil{ fmt.Println("Initsetingerror:",......
  • golang之http请求库go-resty
     github: https://github.com/go-resty/resty go-resty特性#go-resty 有很多特性:发起GET,POST,PUT,DELETE,HEAD,PATCH,OPTIONS,etc.请求简单的链式书写自动解析JSON和XML类型的文档上传文件重试功能客户端测试功能RestyclientCustom RootCertificates andC......
  • 【Netty】「萌新入门」(三)ChannelFuture 与 CloseFuture
    前言本篇博文是《从0到1学习Netty》中入门系列的第三篇博文,主要内容是介绍Netty中ChannelFuture与CloseFuture的使用,解决连接问题与关闭问题,往期系列文章请访问博主的Netty专栏,博文中的所有代码全部收集在博主的GitHub仓库中;连接问题与ChannelFuture在Netty中,所有的......
  • Golang起步篇
    一.安装Go语言开发环境1.Wondows下搭建Go开发环境(1).下载SDK工具包sdk下载地址为:https://go.dev/dl/(2).解压下载的压缩包,放到特定的目录下,我一般放在d:/programs下(路径不能有中文或者特殊符号如空格等)(3).配置环境变量步骤1:先打开环境变量配置的界面步骤2:配置......
  • golang解决go get下载失败解决办法
    原因:所下载的库依赖有官方库,而官方被封禁网导致。方法:设置代理goenv-wGOPROXY=https://goproxy.cnps:go1.11发布后,还发布一个goproxy提供代理服务,goproxy.cn是专门服务于中国的,依赖于七牛云github地址:https://github.com/goproxy......
  • golang汇编学习(寄存器)
    好久没有写博客了,上一篇写的汇编只是简单的调试了一下,这段时间又看了下,做一个简单的汇总。两个代码汇编代码,1_amd64.sTEXT·add(SB),$0-0MOVQa+0(FP),AXMOVQb+8(FP),BXADDQAX,BXMOVQBX,c+16(FP)RET主函数1.gopackagemainfuncadd(a,bint)intfuncmain()......
  • CentOS 9 x64 使用 Nginx、Supervisor 部署 Go/Golang 服务
    前言在CentOS9x64系统上,可以通过以下步骤来部署Golang服务。1.安装必要的软件包安装以下软件包:Golang:Golang编程语言Nginx:Web服务器Supervisor:进程管理工具Git:版本控制工具EPEL:扩展软件包可以通过以下命令来安装:yum-yupdateyuminstallnginxgolangepel-......
  • CentOS 9 x64 使用 Nginx、Supervisor 部署 Go/Golang 服务
    前言在CentOS9x64系统上,可以通过以下步骤来部署Golang服务。1.安装必要的软件包安装以下软件包:Golang:Golang编程语言Nginx:Web服务器Supervisor:进程管理工具Git:版本控制工具EPEL:扩展软件包可以通过以下命令来安装:yum-yupdateyuminstallnginxgolangepel......