Go 学习笔记(二十九)惰性数值生成器
本文原创地址:博客园骏马金龙Go 基础系列:惰性数值生成器
惰性数值生成器是指在需要的时候才生成下一个数值,不需要的时候就卡在那。这和 python 的列表推导表达式类似。惰性生成器的好处是不会一次性将全部结果返回或放进内存,而是每次只返回一个,这样不会在某一时刻大量占用内存和其它资源。
比如,要生成 10W 个数值,如果要迭代这 10W 个数值,有两种方法。第一种方法是将 10W 个数值全部生成好放进一个数组 (或其它数据结构),然后再去数组中取数据。第二种方法是迭代到哪个数值的时候临时去生成这个数值。它们的区别是显然的:第一种方法会占用大量内存,且速度有可能会很慢,第二种方法每次只占用一个数值的内存空间,用完就丢了。
下面是一个不算完美的惰性数值生成器示例:
package main
import (
"fmt"
)
func generateNums(nums chan int) {
num := 0
go func() {
for {
num++
nums <- num
}
}()
}
func getNums(nums chan int) int {
return <-nums
}
func main() {
nums := make(chan int)
generatenums(nums)
for i := 0; i < 10; i++ {
fmt.Println(getnums(nums))
}
}
其中 generateNums() 函数是惰性数值生成器,它使用一个 nums channel 作为参数,每次生成的数值都会放进这个 channel 中。
getNums() 函数是取出存入 nums channel 中的数并返回。
理论上一切都很简单,只要在需要的地方调用 generateNums()函数即可。但问题在于如果多个地方调用 generateNums(),各个地方的 nums 通道将互相影响。所以,应该改进一下,让 generateNums()自带属于自己的 nums 通道,而不是多个 generateNums() 共享一个 nums 通道。
func generateNums(nums chan int) {}
func generateNums(){
nums := make(chan int)
}
因为通道私有了,要想从这个通道中取数据,需要将这个通道作为返回值:
func generateNums() chan int{
nums := make(chan int)
...
return nums
}
这样每次调用 generateNums() 就取得了它的数值生成器通道:
nums := generateNums()
下面是改良后的惰性数值生成器:
package main
import (
"fmt"
)
func generatenums() chan int {
nums := make(chan int)
num := 0
go func() {
for {
num++
nums <- num
}
}()
return nums
}
func getnums(nums chan int) int {
return <-nums
}
func main() {
nums := generatenums()
for i := 0; i < 10; i++ {
fmt.Println(getnums(nums))
}
}
上一篇 Go 学习笔记(二十八)Go 实现工作池的两种方式
Go 学习笔记(目录)
下一篇 Go 学习笔记(三十)Handler