mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-11-13 17:36:12 +08:00
@@ -11,7 +11,7 @@
|
||||
|
||||
生成器每次返回的是序列中下一个值而非整个序列;这种特性也称之为惰性求值:只在你需要时进行求值,同时保留相关变量资源(内存和 CPU):这是一项在需要时对表达式进行求值的技术。例如,生成一个无限数量的偶数序列:要产生这样一个序列并且在一个一个的使用可能会很困难,而且内存会溢出!但是一个含有通道和 go 协程的函数能轻易实现这个需求。
|
||||
|
||||
在 14.12 的例子中,我们实现了一个使用 int 型通道来实现的生成器。通道被命名为 `yield` 和 `resume` ,这些词经常在协程代码中使用。
|
||||
在 14.12 的例子中,我们实现了一个使用 `int` 型通道来实现的生成器。通道被命名为 `yield` 和 `resume` ,这些词经常在协程代码中使用。
|
||||
|
||||
示例 14.12 [lazy_evaluation.go](examples/chapter_14/lazy_evaluation.go):
|
||||
|
||||
@@ -50,7 +50,7 @@ func main() {
|
||||
|
||||
有一个细微的区别是从通道读取的值可能会是稍早前产生的,并不是在程序被调用时生成的。如果确实需要这样的行为,就得实现一个请求响应机制。当生成器生成数据的过程是计算密集型且各个结果的顺序并不重要时,那么就可以将生成器放入到 go 协程实现并行化。但是得小心,使用大量的 go 协程的开销可能会超过带来的性能增益。
|
||||
|
||||
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器的工厂函数 `BuildLazyEvaluator`(这个应该放在一个工具包中实现)。工厂函数需要一个函数和一个初始状态作为输入参数,返回一个无参、返回值是生成序列的函数。传入的函数需要计算出下一个返回值以及下一个状态参数。在工厂函数中,创建一个通道和无限循环的 go 协程。返回值被放到了该通道中,返回函数稍后被调用时从该通道中取得该返回值。每当取得一个值时,下一个值即被计算。在下面的例子中,定义了一个 `evenFunc` 函数,其是一个惰性生成函数:在 main 函数中,我们创建了前 10 个偶数,每个都是通过调用 `even()` 函数取得下一个值的。为此,我们需要在 `BuildLazyIntEvaluator` 函数中具体化我们的生成函数,然后我们能够基于此做出定义。
|
||||
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器的工厂函数 `BuildLazyEvaluator`(这个应该放在一个工具包中实现)。工厂函数需要一个函数和一个初始状态作为输入参数,返回一个无参、返回值是生成序列的函数。传入的函数需要计算出下一个返回值以及下一个状态参数。在工厂函数中,创建一个通道和无限循环的 go 协程。返回值被放到了该通道中,返回函数稍后被调用时从该通道中取得该返回值。每当取得一个值时,下一个值即被计算。在下面的例子中,定义了一个 `evenFunc` 函数,其是一个惰性生成函数:在 `main()` 函数中,我们创建了前 10 个偶数,每个都是通过调用 `even()` 函数取得下一个值的。为此,我们需要在 `BuildLazyIntEvaluator` 函数中具体化我们的生成函数,然后我们能够基于此做出定义。
|
||||
|
||||
示例 14.13 [general_lazy_evalution1.go](examples/chapter_14/general_lazy_evalution1.go):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user