🌀

Golangでのイテレータの使い方

2024/11/22に公開

Goでは、標準ライブラリで直接的なイテレータ構造を提供していないため、開発者が必要に応じてイテレータを実装する方法を知っておくと便利です。ここでは、簡単に実装できるイテレータの方法と、Go 1.23のiterパッケージを利用した反復処理について紹介します。

なぜイテレータが便利なのか?

イテレータは、コレクションやデータのシーケンスを扱う際に役立つツールです。イテレータを使用すると、データを逐次的に取得することができるため、メモリ効率の向上やコードのシンプル化が図れます。

1. 基本的なイテレータの実装

まずは、Goで基本的なイテレータを実装する方法を見てみましょう。たとえば、整数のシーケンスを生成するイテレータを作成するには、次のような関数を利用できます。

package main

import "fmt"

// intIterator は整数を逐次返す関数
func intIterator(max int) func() (int, bool) {
    current := 0
    return func() (int, bool) {
        if current >= max {
            return 0, false // 終了
        }
        value := current
        current++
        return value, true
    }
}

func main() {
    nextInt := intIterator(5)
    for {
        if val, ok := nextInt(); ok {
            fmt.Println(val) // 0, 1, 2, 3, 4 が出力される
        } else {
            break
        }
    }
}

このコードでは、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 := 0; i < 5; i++ {
            if !yield(i) {
                break
            }
        }
    }

    next, stop := iter.Pull(seq)
    defer stop()

    for {
        if val, ok := next(); ok {
            fmt.Println(val) // 0, 1, 2, 3, 4 が出力される
        } else {
            break
        }
    }
}

この例では、Pull関数を使ってseqの各要素を取得しています。defer stop()によってイテレータの停止を確実に行い、リソース管理をシンプルにしています。

キーと値のシーケンス: Seq2

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 {
        if key, value, ok := next(); ok {
            fmt.Printf("%s: %d\n", key, value) // apple, banana, cherry が出力される
        } else {
            break
        }
    }
}

このコードでは、mapのキーと値を逐次的に取得するイテレータを作成しています。iter.Pull2関数によって、キーと値のペアを簡単に取得できます。

まとめ

Golangにおけるイテレータは、シンプルな反復処理を行いたい場合に役立ちます。Go 1.23で導入されたiterパッケージは、カスタムイテレータの作成をサポートし、より効率的で柔軟な反復処理を実現します。

イテレータの基本的な使用方法と、iterパッケージの活用法を理解することで、Goでのデータ処理がより直感的かつ効率的になるでしょう。ぜひ実際に試してみてください!

Discussion