go中的迭代器

语法gojavascript
创建时间: 2024-08-17 23:11:13修改时间: 2024-09-16 16:46:40

前言

一开始我以为迭代器简单,就是用一个for循环一直迭代迭代下去就可以了,直到今天,go 1.23出现,新增了 “range-over-func” 语法。趁着今天有时间,就来研究一下这个新语法。

官方的实例

“for-range”循环中的“range”子句现在接受以下类型的迭代器函数

func(func() bool) func(func(K) bool) func(func(K, V) bool)

javascript中的迭代器

因为此前我接触最多的语言是javascript,所以我先研究了一下javascript语言中的迭代器,在MDN文档中,这部分内容被称之为 "生成器函数" 使用function*来声明的函数都叫生成器函数。

语法如下:

function* generator(i) { yield i; yield i + 10; } const gen = generator(10); console.log(gen.next().value); // Expected output: 10 console.log(gen.next().value); // Expected output: 20

其实看上述的例子就能很清楚的知道这个生成器函数是如何使用的了,无非就是函数中调用了多少次yield,这个生成器生成的迭代器就能调用多少次,比如我需要写一个从n开始一直++的迭代器,实现如下:

function* ttt(n) { for (; ;) { yield n++ } } const t = ttt(1) console.log(t.next()); // 1 console.log(t.next()); // 2 console.log(t.next()); // 3 console.log(t.next()); // 4 console.log(t.next()); // 5

这个迭代器有一个缺陷,就是无法重置迭代器,我们可以将上面的代码优化成如下:

// 下面这段代码中,可以通过 向next函数中传递bool类型的值来重置迭代器 function* ttt(n) { let i = n for (; ;) { // 这个yield的返回值就是每次迭代是next函数中的形参 const status = yield n++ if (status) { n = i } } } const t = ttt(1) console.log(t.next().value); // 1 console.log(t.next().value); // 2 // 通过向next传递true使if中的表达式成立 console.log(t.next(true).value); // 1 console.log(t.next().value); // 2 console.log(t.next().value); // 3

上面就是javascript中的例子

go语言中的迭代器

创建迭代器

go语言中的迭代器正如官方所说的三种类型,三种类型对应的实现每个数依次++迭代如下

// 第一个函数我不是很清楚具体有啥作用,因为没有返回值 // func(func() bool) func numAdd1() func(yield func() bool { return func(yield func() bool) { yield() } } // func(func(K) bool) func numAdd2(n int) func(yield func(int) bool) { return func(yield func(int) bool) { num := n for yield(num) { num++ } } } // 第三中方法可以返回两个参数,其中一个参数可以为迭代的索引 // func(func(K, V) bool) func numAdd2(n int) func(yield func(int, int) bool) { return func(yield func(int, int) bool) { num := n index := 0 for yield(index, num) { num++ index++ } } }

使用迭代器

上面我们创建了迭代器,那么下面我们来使用迭代器,使用迭代器有两种方法,一种是使用for range 语法,另一种是使用回调函数式写法,写法如下:

// 这里只展示第三中案例,因为第三种拥有两个参数,另外两个是通用的 // 第一种方式 ,使用for range来实现迭代 for i, v := range numAdd2(10) { if v >= 20 { break } fmt.Println(i, ":", v) } // 第二中方式 numAdd2(10)(func(i int, v int) bool { fmt.Println(i, ":", v) // 回掉函数中 返回true代表迭代器正常执行,返回false,终止迭代器执行 //(这个返回产生实际上就是yield(index, num)这个函数的返回值) return v < 20 })

总结

上面就是我觉得go 1.23的最大亮点,接下来可以在项目中无忧无虑的使用这个语法了,虽然我可能用不到,不过我还是想说go YYDS

评论