如何解决如何比较Go中渠道的价值 第一次修复removeDuplicates() 现在要修复main()
我有两个频道,首先给我一些字符串,我需要将它们过滤为相同的值,然后将结果发送到第二个频道
func main() {
c := make(chan string,5)
o := make(chan string,5)
arr := []string{"aa","ab","bb","ba","cc"}
for _,v := range arr {
c <- v
go removeDuplicates(c,o)
time.Sleep(1 * time.Second)
fmt.Println("output: ",<-o)
}
}
func removeDuplicates(cIn,cOut chan string) {
last := ""
for cur,isOpen := <-cIn; isOpen; {
if cur != last {
fmt.Printf("val: %s,last: %s\n",cur,last)
last = cur
cOut <- cur
//close(cOut)
}
}
}
我尝试将以前的值保存到“ last”变量,但是当我运行程序时,“ last”为空
val: aa,last:
output: aa
val: ab,last:
output: ab
val: ab,last:
我也不知道在这种情况下何时需要关闭哪些通道。 谢谢您的帮助和关注
解决方法
第一次修复removeDuplicates()
问题是您的for
statement中有一个空的发布声明:
for cur,isOpen := <-cIn; isOpen; {
// ..
}
因此,您从cIn
渠道收到了一次,但是您再也收到不到,因此您在post语句中什么也不做,所以您无休止地重复循环主体。
一旦执行了循环主体,就必须再次接收:
for cur,isOpen := <-cIn; isOpen; cur,isOpen = <-cIn {
// ..
}
这样,输出将是(在Go Playground上尝试):
val: aa,last:
output: aa
val: ab,last: aa
output: ab
val: ab,last:
output: ab
val: bb,last: ab
output: bb
val: bb,last:
output: bb
val: ba,last: ab
output: ba
val: cc,last:
output: cc
但是最好是在频道上使用for range
:
for cur := range cIn {
if cur != last {
fmt.Printf("val: %s,last: %s\n",cur,last)
last = cur
cOut <- cur
}
}
这输出相同。在Go Playground上尝试这个。
现在要修复main()
我们看到“无效”输出,输出中的值仍然重复。
这是因为您启动了多个运行removeDuplicates()
的goroutine。这很不好,因为在输入通道上发送的值将被多个goroutine接收,并且如果一个重复的值未被一个接收,则仍然可以将它们检测为唯一值,因此相同的值将多次发送到输出
只有一个生产者在输入通道上发送所有值,一旦发送完所有值,就关闭通道。
只有一个goroutine使用for range
来过滤值,一旦循环退出(所有输入值都被消耗),就关闭输出通道。
并且有一个goroutine使用for range
从输出通道接收值,因此您可以消除丑陋的time.Sleep
:
func main() {
c := make(chan string,5)
o := make(chan string,5)
go func() {
arr := []string{"aa","ab","bb","ba","cc"}
for _,v := range arr {
c <- v
}
close(c)
}()
go removeDuplicates(c,o)
for v := range o {
fmt.Println("output: ",v)
}
}
func removeDuplicates(cIn chan string,cOut chan string) {
last := ""
for cur := range cIn {
if cur != last {
fmt.Printf("val: %s,last)
last = cur
cOut <- cur
}
}
close(cOut)
}
这将输出(在Go Playground上尝试):
val: aa,last:
val: ab,last: aa
val: bb,last: ab
val: ba,last: bb
val: cc,last: ba
output: aa
output: ab
output: bb
output: ba
output: cc
,
我已注释了代码,以便您理解。请参考以下代码:
package main
import (
"fmt"
"sync"
)
func main() {
var (
c = make(chan string,1)
o = make(chan string,1)
wg = sync.WaitGroup{}
)
stream := []string{"aa","cc"}
wg.Add(1)
// Wait until all the values are received
defer wg.Wait()
// Getter receives the filtered out stream
go getter(o,&wg)
// Removes duplicates from the stream
go removeDuplicates(c,o)
// Send elems to removeDuplicates
for _,elem := range stream {
c <- elem
}
// Close the channel
close(c)
}
// getter recieves the filtered out elements
func getter(cOut <-chan string,wg *sync.WaitGroup) {
defer wg.Done()
for val := range cOut {
fmt.Println("Output: ",val)
}
}
// removeDuplicates removes the adjacent duplicates
func removeDuplicates(cIn chan string,cOut chan string) {
var last string
for cur := range cIn {
if cur != last {
fmt.Printf("val: %s,last)
last = cur
cOut <- cur
}
}
close(cOut)
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。