我正在尝试了解Go语言。我试图创建两个goroutine,使用两个通道将它们之间的流链接起来:
func main() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
for i := range c1{
println("G1 got", i)
c2 <- i
}
}()
go func() {
for i := range c2 {
println("G2 got", i)
c1 <- i
}
}()
c1 <- 1
time.Sleep(1000000000 * 50)
}
如预期的那样,此代码将输出:
G1 got 1
G2 got 1
G1 got 1
G2 got 1
....
直到主要功能退出。
但是,如果我将另一个值从main发送到其中一个通道,则会突然阻塞:
func main() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
for i := range c1{
println("G1 got", i)
c2 <- i
}
}()
go func() {
for i := range c2 {
println("G2 got", i)
c1 <- i
}
}()
c1 <- 1
time.Sleep(1000000000 * 1)
c1 <- 2
time.Sleep(1000000000 * 50)
}
它输出
G1 got 1
G2 got 1
G1 got 1
G2 got 1
G1 got 2
然后阻塞,直到主体结束。
发送给c1的值“ 2”到达第一个goroutie,后者将其发送给c2,但是第二个goroutine从不接收。
(在此示例中,使用大小为1(c1或c2)的缓冲通道)
为什么会发生?当这种情况发生在真实代码中时,我该如何调试呢?
创建的Go通道make(chan int)
未缓冲。如果您想要一个缓冲的通道(不一定会阻塞),请使用make(chan int, 2)
2表示通道的大小。
关于无缓冲通道的事情是它们也是同步的,因此它们总是在 写 和读时阻塞。
之所以陷入僵局,是因为您的第一个goroutine正在等待其c2 <- i
完成,而第二个goroutine正在等待c1 <- i
完成,因为中存在额外的内容c1
。我发现在实际代码中调试此类事件的最佳方法是查看哪些goroutine被阻塞并认真思考。
您也可以仅在确实需要同步通道时才使用同步通道来回避问题。
问题内容: 这是我正在使用的Golang程序,目的只是为了使我的概念正确。当我运行程序时,它陷入了僵局,我不明白为什么?请任何人指出出了什么问题? 输出为: 问题答案: 问题是您要将传递给goroutines 的副本,而不是引用(即指针): 另外,由于是全局变量,您可以完全删除该参数:
因此,服务器和客户端都发生这种情况。我有来自通道活动方法的通道处理程序上下文,我正在尝试使用写入AndFlush(对象消息)方法向其写入对象,但似乎消息永远不会进入创建的管道。 下面是我的客户端处理程序的样子(我重写了包解码器和编码器中的一些方法来调试) 这是我如何写入ChannelHandlerContext通道变量 当我运行我的代码时,“从客户端写入服务器的数据”是打印机,但“在客户端上编码的
问题内容: 我以为直到现在我都了解* nix管道…我有一个名为的可执行文件,它指向我的安装程序的符号链接,我以为我可以使用 但这是行不通的。它给我的效果等同于仅在当前目录中运行。 如果我跑步,我会得到。如果我运行,我得到的预期输出将显示符号链接位置。 那么,为什么管道版本不起作用?我还没为管道抱怨什么? 问题答案: 为此,您需要: 来自: xargs-从标准输入构建和执行命令行 要完全理解管道的工
我试图更多地了解Go的通道和goroutine,所以我决定制作一个小程序,从对象读取的文件中计算单词: 现在,在我发现的大多数示例中,和通道都将被缓冲,比如。但是,在运行这段代码之后,我的程序仍然存在一个错误消息。 基本上,我认为我需要两个通道:一个通道将文件中的行与goroutine通信(因为它可以是任意大小的,所以我不认为我需要在函数调用中通知大小);另一个通道将从goroutine收集结果,
我只是想做一个简单的方法,让我的不和谐机器人加入一个频道。我已经看了多个线程,其中一些已经过时,因为它们是在discord.py迁移到v1.0之前。我已经使用type()和dir()来检查通道是什么类型,并查看它有什么方法。我将其与discord.py的API进行了比较,我发现一个问题是dir()创建了一个名为的字段,但是API显示对象有一个名为方法。感谢所有的帮助!:)
僵尸进程 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。 一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。 理解了孤儿进程和僵尸进程,我们临时加了守护进程这一小节,守护进程就是后台进程吗?没那么简单。