分享
  1. 首页
  2. 文章

关于Golang信号channel的长度问题

钱文品 · · 4579 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

首先来看一下一个简单的信号处理的例子

package main
import (
	"fmt"
	"os"
	"os/signal"
)
func main() {
	c := make(chan os.Signal, 1) # watch this
	signal.Notify(c, os.Interrupt)
	s := <-c
	fmt.Println("Got signal:", s)
}

首先创建一个容纳信号对象的channel,channel的长度为1。

然后使用Notify注册信号处理,将Interrupt信号和channel关联起来。

进程挂在那里休眠,直到收到一个ctrl+c触发了Interrupt信号,channel里就会被塞进一条信号对象,<-c就会返回,打印信号对象然后退出程序。

上面这个例子是官方文档里提供的一个信号处理的简单例子。

值得注意的是这里的channel是非阻塞型channel,长度为1。那能不能是非阻塞型channel呢,能不能是长度为N的阻塞型channel呢?

我们先看看官方的文档里怎么说的

文档里的relay这个单词很有意思,它的英文是传达、转播,有点像代收的意思。

Notify会使得参数c[channel]来代收输入信号。如果信号参数sig未提供,就会代收所有类型的信号。否则只代收参数里提供的信号类型。

信号代收是非阻塞的,什么意思呢?

如果channel满了,被代收的信号就会被抛弃,因为没有空间容纳了。代收的过程等价于

select {
 case c<-sig:
 default:
}

如果channel的长度为1,当一连串的信号同时到达,只会有第一个信号会被代收,如果channel消费者没有来得及处理的话。

如果channel的长度为0,信号可能会丢失。比如下面的代码

package main
import (
	"fmt"
	"os"
	"os/signal"
 "time"
)
func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	time.Sleep(5 * time.Second)
	s := <-c
	fmt.Println("Got signal:", s)
}

我们在程序Sleep的时候狂按ctrl+c持续2秒,然后等待到5秒的Sleep结束,你会发现程序依然挂在那里,不会退出,这时需要再按一下ctrl+c才会退出。

阅读更多相关文章,关注知乎专栏【码洞】


有疑问加站长微信联系(非本文作者)

本文来自:知乎专栏

感谢作者:钱文品

查看原文:关于Golang信号channel的长度问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
4579 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏