[英]how comparing value from channel in Go
我有兩個通道,首先給我一些字符串,我需要過濾到相同的值,然后結果需要發送到第二個通道
func main() {
c := make(chan string, 5)
o := make(chan string, 5)
arr := []string{"aa", "ab", "ab", "bb", "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 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 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", "ab", "bb", "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: %s\n", cur, 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", "ab", "ab", "bb", "bb", "ba", "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: %s\n", cur, last)
last = cur
cOut <- cur
}
}
close(cOut)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.