> ## Content Index
> Fetch the complete content index at: https://huizhou92.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Go 1.23: 新包 Iter
- URL: https://huizhou92.com/go-1-23-new-iter-package-2/
- Published: 2024-06-11T09:33:16.000Z
- Updated: 2026-09-06T11:39:30.000Z
- Author: huizhou92
- Tags: tech, golang, #lang-zh-cn

上周，[Go 1.23](https://tip.golang.org/doc/go1.23?ref=huizhou92.com) 进入冻结期，这意味着不会添加任何新功能，并且任何已添加的功能不太可能被删除。这是一个预览即将发生的变化的好机会。  
这篇文章，来了解一下 1.23 转正的 iter 包。

> This article is first published in the medium MPP plan. If you are a medium user, please follow me in [medium](https://medium.huizhou92.com/?ref=huizhou92.com). Thank you very much.

在Go 1.22中，引入了[range over func](https://go.dev/wiki/RangefuncExperiment?ref=huizhou92.com)实验性功能，但需要通过参数`GOEXPERIMENT=rangefunc`启用。在Go 1.23中，可以直接使用代码实现这种迭代方式。

```go
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   
   }  
 }

```

`yield`是传递给迭代器的可调用函数的常规名称。  
我们考虑一下如何在不使用“iter”包的情况下编写代码来实现相同的功能：

```go
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  
     }  
 }

```

### 性能对比

```shell
➜  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

```

结果很明显：`ToUpperByIter` 性能更好，因为它不会重新分配新的slice，使得它比以前的方法更高效。

## iter 的目标

`iter` 包旨在提供统一且高效的迭代方法。它为自定义容器类（尤其是在引入泛型之后）提供了标准的迭代接口，并可以替换一些返回切片的现有 API。通过使用迭代器并利用编译器优化，可以提高性能。此外，它还提供了适合函数式编程风格的标准迭代机制。

## 如何使用 iter

`iter`支持两种类型的迭代器：

```go
// 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)

```

`map` 包已经使用 `iter` 来添加了诸如 `All` 和 `Keys` 等方法。这里是它的实现参考：

```go
//https://go.googlesource.com/go/blob/c83b1a7013784098c2061ae7be832b2ab7241424/src/maps/iter.go#L12  
 // All returns an iterator over key-value pairs from m.  
 // The iteration order is not specified and is not guaranteed  
 // to be the same from one call to the next.  
 func All[Map ~map[K]V, K comparable, V any](m Map) iter.Seq2[K, V] {  
     return func(yield func(K, V) bool) {  
        for k, v := range m {  
           if !yield(k, v) {  
              return  
           }  
        }  
     }  
 }    
     
 // Keys returns an iterator over keys in m.  
 // The iteration order is not specified and is not guaranteed  
 // to be the same from one call to the next.  
 func Keys[Map ~map[K]V, K comparable](m Map) iter.Seq[K] {  
     return func(yield func(K) bool) {  
        for k := range m {  
           if !yield(k) {  
              return  
           }  
        }  
     }  
 }

```

## 争论

> “在我看来，yield 是一个足够复杂的概念，会导致出现大量糟糕的、难以理解的代码。这个建议只提供了语法糖，用于编写语言中已经超出可能范围的内容。我认为这违背了“一个问题 - 一个解决方案”的规则。拜托，让 Go 保持无聊。” [来源](https://github.com/golang/go/discussions/56413?ref=huizhou92.com#discussioncomment-4060408)

这是社区内常见的反对意见。`yield` 不容易理解，并且我们可以通过多种方式实现迭代器。

## 结论

我支持添加`iter`。

`iter`包为开发人员提供了许多可能性，旨在简化代码并采用更多的函数式编程实践。然而，由于对性能、复杂性和学习曲线的担忧，它的接受度存在分歧。

与任何新工具一样，关键是在提供明显好处的地方平衡其使用，并同时注意潜在缺点。毫无疑问，Go社区将继续探索和辩论如何利用`iter`的力量而不损害该语言的基本原则。

## 参考资料

1. [61405](https://github.com/golang/go/issues/61405?ref=huizhou92.com)
2. [56413](https://github.com/golang/go/discussions/56413?ref=huizhou92.com)
3. [iterators\_in\_go\_123](https://www.reddit.com/r/golang/comments/1d8o01x/iterators%5Fin%5Fgo%5F123/?ref=huizhou92.com)