Posted on:
Last modified:
日常开发中,总有一些文件或者数据过于大而无法放到内存中。在 Python 中,我们可以构造生成器,从而在迭代过程中动态生成元素。而在 Go 语言中没有也不鼓励使用迭代器这种模式,但是观察标准库和一些常见的库,可以看到一些常用的模式。
把所有数据放到一个 slice 中
package main
import "fmt"
func main() {
iter := NewEven()
fmt.Println(iter())
fmt.Println(iter())
fmt.Println(iter())
gen = nil // release for garbage collection
}
func NewEven() func() int {
n := 0
// closure captures variable n
return func() int {
n += 2
return n
}
}
如果不想使用 closure 来保存状态的话,可以使用一个类型来表示。
package main
import "fmt"
func main() {
gen := even(0)
fmt.Println(gen.next())
fmt.Println(gen.next())
fmt.Println(gen.next())
}
type even int
func (e *even) next() int {
*e += 2
return int(*e)
}
不过一般来说复杂一点的对象都会使用 Next() 和 Value() 两个方法,方便在 for 循环中使用,其中 Next() 函数返回是否
package main
import "fmt"
type Range struct {
start int
stop int
step int
current int
}
func (r *Range) Next() bool {
return r.current < r.stop
}
func (r *Range) Value() int {
c := r.current
r.current += r.step
return c
}
func main() {
r := Range{0, 100, 10}
for r.Next() {
fmt.Printf("value is %d", r.Value()
}
}
package main
import "fmt"
func Range(start int, stop int, step int) <-chan int {
ch := make(chan int)
go func() {
for i := start; i < stop; i+= step {
ch <- i
}
close(ch) // Remember to close or the loop never ends!
}()
return ch
}
func main() {
for i := range Range(0, 100, 10) {
fmt.Printf("value is %d", i)
}
}
一般来说,使用 channel 和 closure 的性能不好,而使用有状态的类型性能更好一点。
https://stackoverflow.com/questions/14000534/what-is-most-idiomatic-way-to-create-an-iterator-in-go
© 2016-2022 Yifei Kong. Powered by ynotes
All contents are under the CC-BY-NC-SA license, if not otherwise specified.
Opinions expressed here are solely my own and do not express the views or opinions of my employer.
友情链接: MySQL 教程站