惰性數值生成器是指在需要的時候才生成下一個數值,不需要的時候就卡在那。這和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))
}
}