package main
import (
"fmt"
"strconv"
"time"
)
func generator() chan int {
ch := make(chan int)
go func() {
i := 0
for {
i++
ch <- i
time.Sleep(time.Duration(10) * time.Millisecond)
}
}()
return ch
}
func printer(delay int, square bool, ch chan int) {
for n := range ch {
if (square) {
fmt.Printf("["+strconv.Itoa(n) + "],")
} else {
fmt.Printf("("+strconv.Itoa(n) + "),")
}
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
func sendToBoth(ch chan int) (ch1 chan int, ch2 chan int) {
ch1 = make(chan int)
ch2 = make(chan int)
go func() {
for {
//n := <- ch
select {
case v := <- ch: //this is the problem point
ch1 <- v //
case v := <- ch: //
ch2 <- v //
}
}
}()
return ch1, ch2
}
func main() {
ch1, ch2 := sendToBoth(generator())
go printer(100, true, ch1) //[]
go printer(200, false, ch2) //()
var name string
fmt.Scan(&name)
}
我想实现sendToBoth
函数,该函数从ch channel 获取生成的数字1,2,3,...
,并将其发送到ch1
和ch2
。但是每个都有不同的延迟,并且我不想让一个人等待其他人解锁,因此我尝试使用select
,但无法弄清楚如何查询case子句中是否存在ch1
或ch2
。有什么帮助吗?输出应该像
(1),[1],[2],(2),[3],[4],(3),[5],[6],(4),[7],[8],...
最佳答案
因此,我要说的第一个 react 是“只要让他们同步运行,就会容易得多。”
func sendToBoth(ch chan int) (ch1, ch2 chan int) {
ch1 = make(chan int)
ch2 = make(chan int)
go func() {
defer close(ch1)
defer close(ch2)
for n := range ch {
ch1 <- n
ch2 <- n
}
}()
return ch1, ch2
}
如此简单,我喜欢它!但是,假设您希望ch1和ch2各自消耗自己的速率。如果您希望它们彼此分开,则必须使用临时存储来解决。最简单的方法是给 channel 一些缓冲空间:ch1 = make(chan int, 10)
ch2 = make(chan int, 10)
现在,ch1可以运行得更快-但它只能比ch2提前10个项目。或相反亦然。如果要使用无限大小的缓冲区,则必须自己保留。我们可以利用
nil
channel 完全可以用作select
分支这一事实:func sendToBoth(ch chan int) (ch1, ch2 chan int) {
ch1 = make(chan int)
ch2 = make(chan int)
go func() {
defer close(ch1)
defer close(ch2)
var arr []int
var pos1, pos2 int
ich := ch
for inch != nil && (pos1 < len(arr) || pos2 < len(arr)) {
var och1, och2 chan int
var v1, v2 int
if pos1 < len(arr) {
och1 = ch1
v1 = arr[pos1]
}
if pos2 < len(arr) {
och2 = ch2
v2 = arr[pos2]
}
select {
case n, ok := <- ich:
if !ok {
ich = nil // done
} else {
arr = append(arr, n)
}
case och1 <- v1:
pos1++
case och2 <- v2:
pos2++
}
}
}()
return ch1, ch2
}
稍微复杂一点-我不完全确定这是正确的。另请注意,没有努力释放流中旧项目的存储空间。
关于go - 检查我是否可以从 channel 读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64231097/