注意:泛型 v2 API 仍在开发中,尚未发布,并要求 Go 1.26 或更高版本。如需此前可用的版本,请查看 v1 分支。
C++ STL 迭代器和算法库的 Go 语言实现。
更少的手写循环,更多富有表达力的代码。

动机
Go 现在已经支持泛型,我们值得拥有可复用的通用算法。iter 可以在以下方面帮助改善代码:
有一些开源项目在做类似的事情,比如 gostl,gods 和 go-stp。iter 的独特之处在于:
示例
示例保留包名前缀,以明确对应的泛型 v2 API。完整且可执行的示例见 examples_test.go。
| 控制台输出 list.List |
l := list.New()
for i := 1; i <= 5; i++ {
l.PushBack(i)
}
for e := l.Front(); e != nil; e = e.Next() {
fmt.Print(e.Value)
if e.Next() != nil {
fmt.Print("->")
}
}
// Output:
// 1->2->3->4->5
|
l := list.New()
algo.GenerateN(lists.ListBackInserter[int](l), 5, iter.IotaGenerator(1))
algo.Copy(lists.Begin[int](l), lists.End[int](l), iter.IOWriter[int](os.Stdout, "->"))
// Output:
// 1->2->3->4->5
|
| 反转 string |
s := "!dlrow olleH"
var sb strings.Builder
for i := len(s) - 1; i >= 0; i-- {
sb.WriteByte(s[i])
}
fmt.Println(sb.String())
b := []byte(s)
for i := len(s)/2 - 1; i >= 0; i-- {
j := len(s) - 1 - i
b[i], b[j] = b[j], b[i]
}
fmt.Println(string(b))
// Output:
// Hello world!
// Hello world!
|
s := "!dlrow olleH"
fmt.Println(strs.MakeString(strs.RBegin(s), strs.REnd(s)))
b := []byte(s)
iterslices.Reverse(b)
fmt.Println(string(b))
// Output:
// Hello world!
// Hello world!
|
| 去重(来自 SliceTricks,略微调整) |
in := []int{3, 2, 1, 4, 3, 2, 1, 4, 1}
sort.Ints(in)
j := 0
for i := 1; i < len(in); i++ {
if in[j] == in[i] {
continue
}
j++
in[j] = in[i]
}
in = in[:j+1]
fmt.Println(in)
// Output:
// [1 2 3 4]
|
in := []int{3, 2, 1, 4, 3, 2, 1, 4, 1}
iterslices.Sort(in)
in = iterslices.Unique(in)
fmt.Println(in)
// Output:
// [1 2 3 4]
|
| 对 channel 中的所有整数求和 |
ch := make(chan int)
go func() {
for _, x := range rand.Perm(100) {
ch <- x + 1
}
close(ch)
}()
var sum int
for x := range ch {
sum += x
}
fmt.Println(sum)
// Output:
// 5050
|
ch := make(chan int)
go func() {
algo.CopyN[int](iter.IotaReader(1), 100, iter.ChanWriter(ch))
close(ch)
}()
fmt.Println(algo.Accumulate(iter.ChanReader(ch), nil, 0))
// Output:
// 5050
|
| 删除字符串中的连续空格 |
str := " a quick brown fox "
var sb strings.Builder
var prevIsSpace bool
for i := 0; i < len(str); i++ {
if str[i] != ' ' || !prevIsSpace {
sb.WriteByte(str[i])
}
prevIsSpace = str[i] == ' '
}
fmt.Println(sb.String())
// Output:
// a quick brown fox
|
str := " a quick brown fox "
var sb strs.StringBuilderInserter[byte]
algo.UniqueCopyIf(strs.Begin(str), strs.End(str), &sb,
func(x, y byte) bool { return x == ' ' && y == ' ' })
fmt.Println(sb.String())
// Output:
// a quick brown fox
|
| 收集 channel 中最大的 N 个整数 |
// 需要手动维护小顶堆。
|
top := make([]int, 5)
algo.PartialSortCopyBy(iter.ChanReader(ch), nil, iterslices.Begin(top), iterslices.End(top),
func(x, y int) bool { return x > y })
algo.Copy(iterslices.Begin(top), iterslices.End(top), iter.IOWriter[int](os.Stdout, ", "))
|
| 输出 ["a", "b", "c"] 的所有排列 |
// 通常需要引入递归来完成。
|
s := []string{"a", "b", "c"}
for ok := true; ok; ok = iterslices.NextPermutation(s) {
fmt.Println(s)
}
// Output:
// [a b c]
// [a c b]
// [b a c]
// [b c a]
// [c a b]
// [c b a]
|
致谢
开源许可证
BSD 3-Clause