从频道范围提前返回

时间:2018-11-21 00:22:57

标签: go yield

是否可以从python中实现类似于yield的东西?也就是说,我想要一个生产者/消费者范式,其中消费者可以在不显示内存泄漏的情况下随时忽略生产者产生的值。

在python中,我可以有一个产生无限值的生成器,并且客户端可以消耗任意数量的值。

def producer():
  i = 0
  while True:
     yield i
     i += 1

def consumer():
   for i in producer():
     if i == 2:
        return

通常的建议是,生产者返回客户端在range表达式中使用的通道,生产者可以将其值放入通道中。只要客户端读取通道中的所有值,就可以了,但是如果客户端提前中断range循环的控制,则生产者通道将永久耗尽内存。

package main

func yield() chan int {
    out := make(chan int)
    go func(){
        out <- 1
        out <- 2
        close(out)
    }()
    return out
}

func test(){
    for _ = range yield() {
        // return
    }
}

func main(){
    for {
        test()
    }
}

如果未注释return中的test,则此代码将无限制地使用内存,因为yield返回的通道具有等待读取的值,并且显然没有通道也不能安全地收集goroutine的垃圾。

一些可能的解决方案(我都不喜欢)

  1. out中的yield更改为一个缓冲通道,其空间量将作为要产生的值。在这种情况下,yield可能是

    func yield()chan int {         出:= make(chan int,2)         出<-1         出<-2         关闭(关闭)         返回     }

但这是次优的,因为我一般不知道yield会产生多少个项目。这种样式类似于仅返回数组。

  1. yield方法使用超时将值放入通道中,如果达到超时,则尽早关闭通道。这样就对客户端的执行时间进行了假设,这似乎是个坏主意。

0 个答案:

没有答案