mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 03:06:41 +08:00
@@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
生成器每次返回的是序列中下一个值而非整个序列;这种特性也称之为惰性求值:只在你需要时进行求值,同时保留相关变量资源(内存和cpu):这是一项在需要时对表达式进行求值的技术。例如,生成一个无限数量的偶数序列:要产生这样一个序列并且在一个一个的使用可能会很困难,而且内存会溢出!但是一个含有通道和go协程的函数能轻易实现这个需求。
|
生成器每次返回的是序列中下一个值而非整个序列;这种特性也称之为惰性求值:只在你需要时进行求值,同时保留相关变量资源(内存和cpu):这是一项在需要时对表达式进行求值的技术。例如,生成一个无限数量的偶数序列:要产生这样一个序列并且在一个一个的使用可能会很困难,而且内存会溢出!但是一个含有通道和go协程的函数能轻易实现这个需求。
|
||||||
|
|
||||||
在14.12的例子中,我们实现了一个使用 int 型通道来实现的生成器。通道被命名为`yield`和`resume`,这些此经常在协程代码中使用。
|
在14.12的例子中,我们实现了一个使用 int 型通道来实现的生成器。通道被命名为`yield`和`resume`,这些词经常在协程代码中使用。
|
||||||
|
|
||||||
**Listing 14.12-lazy evaluation.go**
|
示例 14.12 [lazy_evaluation.go](examples/chapter_14/lazy_evaluation.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
@@ -51,10 +52,11 @@ func main() {
|
|||||||
|
|
||||||
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器的工厂函数`BuildLazyEvaluator`(这个应该放在一个工具包中实现)。工厂函数需要一个函数和一个初始状态作为输入参数,返回一个无参、返回值是生成序列的函数。传入的函数需要计算出下一个返回值以及下一个状态参数。在工厂函数中,创建一个通道和无限循环的go协程。返回值被放到了该通道中,返回函数稍后被调用时从该通道中取得该返回值。每当取得一个值时,下一个值即被计算。在下面的例子中,定义了一个`evenFunc`函数,其是一个惰性生成函数:在main函数中,我们创建了前10个偶数,每个都是通过调用`even()`函数取得下一个值的。为此,我们需要在`BuildLazyIntEvaluator`函数中具体化我们的生成函数,然后我们能够基于此做出定义。
|
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器的工厂函数`BuildLazyEvaluator`(这个应该放在一个工具包中实现)。工厂函数需要一个函数和一个初始状态作为输入参数,返回一个无参、返回值是生成序列的函数。传入的函数需要计算出下一个返回值以及下一个状态参数。在工厂函数中,创建一个通道和无限循环的go协程。返回值被放到了该通道中,返回函数稍后被调用时从该通道中取得该返回值。每当取得一个值时,下一个值即被计算。在下面的例子中,定义了一个`evenFunc`函数,其是一个惰性生成函数:在main函数中,我们创建了前10个偶数,每个都是通过调用`even()`函数取得下一个值的。为此,我们需要在`BuildLazyIntEvaluator`函数中具体化我们的生成函数,然后我们能够基于此做出定义。
|
||||||
|
|
||||||
** Listing 14.13: general lazy evaluation1.go **
|
示例 14.13 [general_lazy_evalution1.go](examples/chapter_14/general_lazy_evalution1.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
@@ -119,7 +121,7 @@ func BuildLazyIntEvaluator(evalFunc EvalFunc, initState Any) func() int {
|
|||||||
通过使用14.12中工厂函数生成前10个斐波那契数
|
通过使用14.12中工厂函数生成前10个斐波那契数
|
||||||
|
|
||||||
提示:因为斐波那契数增长很迅速,使用`uint64`类型。
|
提示:因为斐波那契数增长很迅速,使用`uint64`类型。
|
||||||
注:这种计算通常被定义为递归函数,但是在没有尾递归的语言中,例如go语言,这可能会导致栈溢出,但随着go语言中堆栈可扩展的优化,这个问题就不那么严重。这里使用的诀窍使用了惰性求值。gccgo编译器在某些情况下会实现尾递归。
|
注:这种计算通常被定义为递归函数,但是在没有尾递归的语言中,例如go语言,这可能会导致栈溢出,但随着go语言中堆栈可扩展的优化,这个问题就不那么严重。这里的诀窍是使用了惰性求值。gccgo编译器在某些情况下会实现尾递归。
|
||||||
|
|
||||||
## 链接
|
## 链接
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
// general_lazy_evalution1.go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@@ -22,6 +22,7 @@ func integers() chan int {
|
|||||||
func generateInteger() int {
|
func generateInteger() int {
|
||||||
return <-resume
|
return <-resume
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
resume = integers()
|
resume = integers()
|
||||||
fmt.Println(generateInteger()) //=> 0
|
fmt.Println(generateInteger()) //=> 0
|
||||||
|
Reference in New Issue
Block a user