前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 1.23:拥抱iter包,简化你的迭代逻辑

Go 1.23:拥抱iter包,简化你的迭代逻辑

作者头像
crossoverJie
发布2024-07-01 12:48:40
680
发布2024-07-01 12:48:40
举报
文章被收录于专栏:crossoverJiecrossoverJie

最近 Go1.23 进入了冻结阶段,意味着不再添加新功能,而且已经加入的功能也不再会删除。

Go 1.23 正式引入了 iter 软件包,这是一个专门用于 Iterators 的新特性。

该软件包在 Go 1.22 中作为实验性功能,需要通过 GOEXPERIMENT=rangefunc 参数启用。

在 Go 1.23 中,开发者可以直接通过代码实现迭代。

在这之前循环将切片数据全部转换为大写时的写法:

代码语言:javascript
复制
func Convert[S any, D any](src []S, mapFn func(s S) D) []D {  
     r := make([]D, 0, len(src))  
     for _, i := range src {  
        r = append(r, mapFn(i))  
     }  
     return r  
 }  
   
 func ToUpByString() {  
     sl := []string{"hello", "world", "golang"}  
     s0 := Convert(sl, func(v string) string { return strings.ToUpper(v) })  
     for _, v := range s0 {  
        // do business
     }  
 }

而在使用新的 Iter 迭代器之后:

代码语言:javascript
复制
func Backward(s []string) func(yield func(string) bool) {
   return func(yield func(string) bool) {
     for i := len(s) - 1; i >= 0; i-- {
       yield(strings.ToUpper(s[i]))
     }
   }
 }
 
 func ToUpperByIter() {
   sl := []string{"hello", "world", "golang"}
   for v := range Backward(sl) {
     // do business 
   }
 }

可以发现明显的代码量减少了,同时更符合函数式编程的特性。

通过性能比较,ToUpperByIter 方法性能更高,因为它不需要重新分配新的切片。

代码语言:javascript
复制
➜  huizhou92 git:(master) ✗ go test -bench . -count=3
 goos: darwin
 goarch: arm64
 pkg: huizhou92
 cpu: Apple M1 Pro
 BenchmarkToUpByString-10         8568332               128.7 ns/op
 BenchmarkToUpByString-10         9310351               128.6 ns/op
 BenchmarkToUpByString-10         9344986               128.5 ns/op
 BenchmarkToUpByIter-10          12440120                96.22 ns/op
 BenchmarkToUpByIter-10          12436645                96.25 ns/op
 BenchmarkToUpByIter-10          12371175                96.64 ns/op
 PASS
 ok      huizhou92       8.162s

iter 软件包提供了两种迭代器类型:

  • Seq 用于单个值的迭代
  • Seq2 用于键值对的迭代。

具体函数声明如下:

代码语言:javascript
复制
// Seq is an iterator over sequences of individual values.
 // When called as seq(yield), seq calls yield(v) for each value v in the sequence,
 // stopping early if yield returns false.  
 type Seq[V any] func(yield func(V) bool)  
   
 // Seq2 is an iterator over sequences of pairs of values, most commonly key-value pairs.
 // When called as seq(yield), seq calls yield(k, v) for each pair (k, v) in the sequence,
 // stopping early if yield returns false.  
 type Seq2[K, V any] func(yield func(K, V) bool)

iter 软件包的目标是提供一种统一和高效的迭代方法,并且已经在 map 包中添加了 AllKeys 等方法。

具体列表如下:

而社区对于 yielditer 的引入有不同意见,有人认为它会引入复杂性和难以可理解的代码,而另一些则认为它能够帮助开发者简化代码并采用更多函数式编程。

个人觉得 Go 在新版本映入一些新特性是有必要的,这样才能保持社区的活跃,同时选择权也是交给开发者的。

类似的在 Java8 中引入的 lambda 表达式起初也是有很多人反馈难以阅读与调试,经过这么多年的普及以及 IDE 的支持,现在已经成为大多数开发者的标配了。

参考链接:

  • https://tip.golang.org/doc/go1.23#iterators
  • https://levelup.gitconnected.com/go-1-23-new-iter-package-4ae649a0e910
  • https://pkg.go.dev/iter@master#hdr-Iterators
  • https://github.com/golang/go/discussions/56413#discussioncomment-4060408
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 crossoverJie 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档