doujia1939 2012-12-22 06:08
浏览 209
已采纳

在Go中创建迭代器的最惯用的方法是什么?

One option is to use channels. Channels are like iterators in a way and you can iterate over them using range keyword. But when you find out you can't break out of this loop without leaking goroutine the usage becomes limited.

What is the idiomatic way to create iterator pattern in go?

Edit:

The fundamental problem with channels is they are a push model. Iterator is is a pull model. You don't have to tell iterator to stop. I'm looking for a way to iterate over collections in a nice expressive way. I would also like to chain iterators (map, filter, fold alternatives).

  • 写回答

8条回答 默认 最新

  • dongzengzai4567 2012-12-22 12:18
    关注

    Channels are useful, but closures are often more suitable.

    package main
    
    import "fmt"
    
    func main() {
        gen := newEven()
        fmt.Println(gen())
        fmt.Println(gen())
        fmt.Println(gen())
        gen = nil // release for garbage collection
    }
    
    func newEven() func() int {
        n := 0
        // closure captures variable n
        return func() int {
            n += 2
            return n
        }
    }
    

    Playground: http://play.golang.org/p/W7pG_HUOzw

    Don't like closures either? Use a named type with a method:

    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)
    }
    

    Playground: http://play.golang.org/p/o0lerLcAh3

    There are tradeoffs among the three techniques so you can't nominate one as idiomatic. Use whatever best meets your needs.

    Chaining is easy because functions are first class objects. Here's an extension of the closure example. I added a type intGen for integer generator which makes it clear where generator functions are used as arguments and return values. mapInt is defined in a general way to map any integer function to an integer generator. Other functions such as filter and fold could be defined similarly.

    package main
    
    import "fmt"
    
    func main() {
        gen := mapInt(newEven(), square)
        fmt.Println(gen())
        fmt.Println(gen())
        fmt.Println(gen())
        gen = nil // release for garbage collection
    }
    
    type intGen func() int
    
    func newEven() intGen {
        n := 0
        return func() int {
            n += 2
            return n
        }
    }
    
    func mapInt(g intGen, f func(int) int) intGen {
        return func() int {
            return f(g())
        }
    }
    
    func square(i int) int {
        return i * i
    }
    

    Playground: http://play.golang.org/p/L1OFm6JuX0

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(7条)

报告相同问题?

悬赏问题

  • ¥15 onlyoffice编辑完后立即下载,下载的不是最新编辑的文档
  • ¥15 求caverdock使用教程
  • ¥15 Coze智能助手搭建过程中的问题请教
  • ¥15 12864只亮屏 不显示汉字
  • ¥20 三极管1000倍放大电路
  • ¥15 vscode报错如何解决
  • ¥15 前端vue CryptoJS Aes CBC加密后端java解密
  • ¥15 python随机森林对两个excel表格读取,shap报错
  • ¥15 基于STM32心率血氧监测(OLED显示)相关代码运行成功后烧录成功OLED显示屏不显示的原因是什么
  • ¥100 X轴为分离变量(因子变量),如何控制X轴每个分类变量的长度。