Golangでのイテレータの使い方
Goでは、標準ライブラリで直接的なイテレータ構造を提供していないため、開発者が必要に応じてイテレータを実装する方法を知っておくと便利です。ここでは、簡単なイテレータの実装方法とGo 1.23のiter
パッケージを利用した反復処理について紹介します。
なぜイテレータが便利なのか?
イテレータはコレクションやデータのシーケンスを扱う際に役立つ仕組みです。イテレータを使用すると、データを逐次的に取得することができるため、メモリ効率の向上やコードのシンプル化が図れます。
1. 基本的なイテレータの実装
まずは、Goで基本的なイテレータを実装する方法を見てみましょう。たとえば、整数のシーケンスを生成するイテレータを作成するには次のようにします。
package main
import "fmt"
// intIterator は整数を逐次返す関数
func intIterator(max int) func() (int, bool) {
cur := 0
return func() (int, bool) {
if max <= cur {
return 0, false // 終了
}
v := cur
cur++
return v, true
}
}
func main() {
nextInt := intIterator(5)
for {
v, ok := nextInt()
if !ok {
break
}
fmt.Println(v) // 0, 1, 2, 3, 4 が出力される
}
}
このコードでは、intIterator
関数がイテレータを返します。このイテレータは毎回1つの整数を返し、指定された上限まで進むと終了します。
2. Go 1.23のiterパッケージを使ったイテレータ
Go 1.23では、新たにiter
パッケージが追加され、より便利なイテレータを提供しています。iter
パッケージでは、シーケンスやキーと値のペアを扱うための機能が強化されており、カスタムのイテレータを作成しやすくなっています。
Seq
を使ったシーケンス生成
Seq
型は、データシーケンスを扱うための関数型で、yield
関数を利用してデータを逐次返します。以下は、Seq
を使って0から4までの整数を出力する例です。
package main
import (
"fmt"
"iter"
)
func main() {
// 0から4までの整数シーケンスを生成
seq := func(yield func(int) bool) {
for i := range 5 {
if !yield(i) {
break
}
}
}
next, stop := iter.Pull(seq)
defer stop()
for {
v, ok := next()
if !ok {
break
}
fmt.Println(v) // 0, 1, 2, 3, 4 が出力される
}
}
この例では、Pull
関数を使ってseq
の各要素を取得しています。defer stop()
によってイテレータの停止を確実に行い、リソース管理をシンプルにしています。
キーと値のシーケンス
Seq2
は、キーと値のペアを持つシーケンスです。以下の例では、文字列とその長さのペアを生成するイテレータを作成しています。
package main
import (
"fmt"
"iter"
)
func main() {
seq2 := func(yield func(string, int) bool) {
items := map[string]int{"apple": 5, "banana": 6, "cherry": 6}
for k, v := range items {
if !yield(k, v) {
break
}
}
}
next, stop := iter.Pull2(seq2)
defer stop()
for {
k, v, ok := next()
if !ok {
break
}
fmt.Printf("%s: %d\n", k, v) // apple, banana, cherry が出力される
}
}
このコードでは、map
のキーと値を逐次的に取得するイテレータを作成しています。iter.Pull2
関数によってキーと値のペアを簡単に取得できます。
まとめ
Golangのイテレータはシンプルな反復処理を行いたい場合に役立ちます。Go 1.23で導入されたiter
パッケージは、カスタムイテレータの作成をサポートし、より効率的で柔軟な反復処理を実現します。
イテレータの基本的な使用方法とiter
パッケージの活用法を理解することで、Goでのデータ処理がより直感的かつ効率的になるでしょう。ぜひ実際に試してみてください!
Discussion