通道发送,但接收方只接收到每隔一个消息。

huangapple go评论83阅读模式
英文:

Channel sending but receiver only receives every other message

问题

我正在尝试编写一个程序,其中生成通道并通过管道传递信息。我有一个通道从上游通道接收信息,然后简单地将其传递给下一个通道,重复一定次数。我的问题是,似乎该函数将输入发送到下一个通道,但在接收端,只有每隔一个消息被接收和打印出来。我不太确定发生了什么。

以下是代码:

// 接收一个 [3]Point3D 数组,并将其发送到 outputStream n 次的函数
func takeN(inputStream <-chan [3]Point3D, closeInputStream chan<- bool, n int) <-chan [3]Point3D {
	outputStream := make(chan [3]Point3D)
	go func() {
		// 接收点 n 次并重新发送
		for i := 0; i < n; i++ {
			in := <-inputStream
			outputStream <- in
			fmt.Println("out from takeN: ", in)
		}

		// 完成管道的初始阶段后终止
		closeInputStream <- true

		// 关闭输出流,让下游函数知道不会再有输出
		close(outputStream)
		return
	}()
	return outputStream
}


func main() {

	// 用于发送上游管道停止信号的通道
	stopChan := make(chan bool)
        // 为 takeNChan 生成输入的通道
	singlePointChan := RandomGenerator(stopChan, pointCloud)
	triplePointChan := TripletGenerator(singlePointChan)

	takeNChan := takeN(triplePointChan, stopChan, 10)

        // 这里的问题是:这个打印语句只执行了 5 次,而不是 10 次。即使使用了带缓冲的通道,它也只打印了 5 次
	for range takeNChan {
		received := <-takeNChan
		fmt.Println("main takeNchan: ", received)
	}

	time.Sleep(time.Second * 5)
}

在主函数中,接收到的消息只打印了 5 次(应该是 10 次)。

当我运行代码时,我得到了以下输出:

out from takeN:  [{-2.74 -11.45 2.52} {-7.26 -11.21 2.72} {9.96 -1.3 -0.83}]
out from takeN:  [{5.46 2.68 -0.72} {1.15 -11.61 3.18} {0.22 -3.58 -0.29}]  
main takeNchan:  [{5.46 2.68 -0.72} {1.15 -11.61 3.18} {0.22 -3.58 -0.29}]  
out from takeN:  [{-1.98 -4.16 -0.89} {3.71 -2.35 -0.85} {0.51 4.47 -0.75}] 
out from takeN:  [{0.4 -3.34 0} {63.21 -7.23 2.88} {-1.43 -11.51 3.41}]     
main takeNchan:  [{0.4 -3.34 0} {63.21 -7.23 2.88} {-1.43 -11.51 3.41}]     
out from takeN:  [{-3.61 6.79 0.01} {1.14 5.29 -0.15} {12.73 9.59 2.49}]    
out from takeN:  [{-2.07 -4.47 -0.59} {1.95 2.27 -0.79} {26.1 13.95 -0.27}] 
main takeNchan:  [{-2.07 -4.47 -0.59} {1.95 2.27 -0.79} {26.1 13.95 -0.27}] 
out from takeN:  [{5.39 -0.66 -0.8} {29.96 11.26 0.02} {8.17 9.86 1.76}]    
out from takeN:  [{2.28 2.21 -0.77} {6.91 -7.32 -0.55} {4.77 -0.25 -0.79}]  
main takeNchan:  [{2.28 2.21 -0.77} {6.91 -7.32 -0.55} {4.77 -0.25 -0.79}]  
out from takeN:  [{-0.99 -3.73 -0.46} {-4.26 7.85 -0.65} {1.33 -11.6 3.57}] 
out from takeN:  [{5.31 -11.23 -0.11} {2.01 2.47 -0.78} {5.24 -11.25 -0.45}]
main takeNchan:  [{5.31 -11.23 -0.11} {2.01 2.47 -0.78} {5.24 -11.25 -0.45}]

如你所见,在主函数中,只有每隔一个输出被接收和打印了 5 次,而每隔一个消息从 takeN 函数发送。

根据我的理解,"out from takeN" 的打印语句应该在前一行发送消息后执行,因为 goroutine 中的代码是顺序执行的,对吗?我认为在没有接收者准备好之前,消息不应该被发送出通道,那为什么消息被发送出去却似乎没有被接收呢?

程序在最后会停顿一段时间,因为有一个 time.Sleep,所以我不认为是主程序提前退出了。
我还尝试过将输出通道设置为带缓冲,但也没有起作用。

英文:

I'm trying to write a program where channels are generated and information is passed through a pipeline. I have one channel that is receiving from an upstream channel and simply passing it down to the next channel, for a certain number of times. My problem is that it seems like that function is sending the inputs to the next channel, but on the receiving side, only every other message is received and printed. I'm not quite sure what is going on.

Here is the code:

//Function that receives an array of [3]Point3D, and then sends it to the outputStream n times
func takeN(inputStream &lt;-chan [3]Point3D, closeInputStream chan&lt;- bool, n int) &lt;-chan [3]Point3D {
	outputStream := make(chan [3]Point3D)
	go func() {
		//Receives points n times and resends them
		for i := 0; i &lt; n; i++ {
			in := &lt;-inputStream
			outputStream &lt;- in
			fmt.Println(&quot;out from takeN: &quot;, in)
		}

		//Terminate initial stage of the pipeline once done
		closeInputStream &lt;- true

		//Close the output stream to let downstream functions know there won&#39;t be any more outputs
		close(outputStream)
		return
	}()
	return outputStream
}


func main() {

	// Channel used to send the stop signal for the upstream portion of the pipeline
	stopChan := make(chan bool)
        //Channels that generate inputs for takeNChan
	singlePointChan := RandomGenerator(stopChan, pointCloud)
	triplePointChan := TripletGenerator(singlePointChan)

	takeNChan := takeN(triplePointChan, stopChan, 10)

        //Here is the problem: this print statement is only executed 5 times, when it should be executed 10 times. Even with a buffered channel, it only prints 5 times
	for range takeNChan {
		received := &lt;-takeNChan
		fmt.Println(&quot;main takeNchan: &quot;, received)
	}

	time.Sleep(time.Second * 5)
}

In the main function, the received message is only printed 5 times (should be 10).

When I run the code, I get the following output:

out from takeN:  [{-2.74 -11.45 2.52} {-7.26 -11.21 2.72} {9.96 -1.3 -0.83}]
out from takeN:  [{5.46 2.68 -0.72} {1.15 -11.61 3.18} {0.22 -3.58 -0.29}]  
main takeNchan:  [{5.46 2.68 -0.72} {1.15 -11.61 3.18} {0.22 -3.58 -0.29}]  
out from takeN:  [{-1.98 -4.16 -0.89} {3.71 -2.35 -0.85} {0.51 4.47 -0.75}] 
out from takeN:  [{0.4 -3.34 0} {63.21 -7.23 2.88} {-1.43 -11.51 3.41}]     
main takeNchan:  [{0.4 -3.34 0} {63.21 -7.23 2.88} {-1.43 -11.51 3.41}]     
out from takeN:  [{-3.61 6.79 0.01} {1.14 5.29 -0.15} {12.73 9.59 2.49}]    
out from takeN:  [{-2.07 -4.47 -0.59} {1.95 2.27 -0.79} {26.1 13.95 -0.27}] 
main takeNchan:  [{-2.07 -4.47 -0.59} {1.95 2.27 -0.79} {26.1 13.95 -0.27}] 
out from takeN:  [{5.39 -0.66 -0.8} {29.96 11.26 0.02} {8.17 9.86 1.76}]    
out from takeN:  [{2.28 2.21 -0.77} {6.91 -7.32 -0.55} {4.77 -0.25 -0.79}]  
main takeNchan:  [{2.28 2.21 -0.77} {6.91 -7.32 -0.55} {4.77 -0.25 -0.79}]  
out from takeN:  [{-0.99 -3.73 -0.46} {-4.26 7.85 -0.65} {1.33 -11.6 3.57}] 
out from takeN:  [{5.31 -11.23 -0.11} {2.01 2.47 -0.78} {5.24 -11.25 -0.45}]
main takeNchan:  [{5.31 -11.23 -0.11} {2.01 2.47 -0.78} {5.24 -11.25 -0.45}]

As you can see, only every other output is received and printed in the main() function 5 times, with every other message sent from the takeN function.

From my understanding, the print "out from takeN" should only execute once a message is sent on the line before because the code within the goroutine is sequential right? I thought that messages shouldn't be sent out of the channel until there is a receiver ready, so why are messages being sent out and seemingly not received?

The program hangs for a bit at the end due to the time.Sleep, so I don't think it's because the main program is exiting early.
I've also tried making the output channel buffered but that didn't work either.

答案1

得分: 1

你正在从通道中接收两次,并且丢弃第一个值。将其更改为:

for received := range takeNChan {
    fmt.Println("main takeNchan: ", received)
}
英文:

You are receiving from the channel twice - and discarding the first value. Change this:

for range takeNChan {
    received := &lt;-takeNChan
    fmt.Println(&quot;main takeNchan: &quot;, received)
}

to:

for received := range takeNChan {
    fmt.Println(&quot;main takeNchan: &quot;, received)
}

huangapple
  • 本文由 发表于 2023年2月23日 04:43:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75537966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定