イテレータ型
json パッケージは多様なイテレータ型を提供し、順次走査、ストリーミング処理、バッチ処理、並列処理の各シナリオをカバーします。反復関数(Foreach/ForeachFile など)は パッケージレベル反復関数 と Processor 反復メソッド を参照してください。
IteratorControl 定数
IteratorControl は反復制御フラグを表し、ForeachWithPathAndControl と ForeachWithPathAndIterator で反復フローを制御するために使用します。
| 定数 | 説明 |
|---|---|
IteratorNormal | 通常通り反復を継続(デフォルト値) |
IteratorContinue | 現在の要素をスキップして反復を継続 |
IteratorBreak | 反復を停止 |
使用シナリオ
| シナリオ | 推奨戻り値 | 説明 |
|---|---|---|
| 通常の要素処理 | IteratorNormal | 次の要素の処理を継続 |
| 無効データのフィルタリング | IteratorContinue | 現在の要素をスキップ、反復は中断しない |
| ターゲット発見後の終了 | IteratorBreak | 必要なデータが見つかったら即座に停止 |
| エラー発生時の中断 | IteratorBreak | 重大なエラーが発生したら反復を停止 |
Iterator 型
Iterator は JSON 配列またはオブジェクトを走査するための低レベルイテレータです。
NewIterator
シグネチャ:func NewIterator(data any, cfg ...Config) *Iterator
イテレータインスタンスを作成します。
data := []any{"apple", "banana", "cherry"}
it := json.NewIterator(data)
for it.HasNext() {
val, _ := it.Next()
fmt.Println(val)
}メソッド
| メソッド | シグネチャ | 説明 |
|---|---|---|
HasNext | func (it *Iterator) HasNext() bool | 次の要素があるかチェック |
Next | func (it *Iterator) Next() (any, bool) | 次の要素を取得 |
Reset | func (it *Iterator) Reset() | イテレータの状態とキャッシュをクリア、再利用の準備 |
ResetWith | func (it *Iterator) ResetWith(data any) | 状態をクリアし、新しいデータで初期化 |
Reset
イテレータの状態をクリアし、キャッシュされたキーを解放します。呼び出し後は ResetWith で再初期化できます。
it := json.NewIterator(data1)
for it.HasNext() {
it.Next()
}
it.Reset() // キャッシュをクリアResetWith
イテレータの状態をクリアし、新しいデータで初期化して、イテレータの再利用を実現します。
it := json.NewIterator(data1)
// ... data1 を走査 ...
it.ResetWith(data2) // イテレータを再利用して新しいデータを走査
for it.HasNext() {
val, _ := it.Next()
fmt.Println(val)
}IterableValue 型
IterableValue は反復プロセス中の現在の要素をラップし、便利な値アクセスメソッドを提供します。Foreach 系関数のコールバックは *IterableValue を受け取ります。
メソッド
GetData
シグネチャ:func (iv *IterableValue) GetData() any
内部データを返します。
Get
シグネチャ:func (iv *IterableValue) Get(path string) any
パスで値を取得(ドット記法と配列インデックスをサポート)。
val := iv.Get("user.address.city")
val = iv.Get("users[0].name")GetString
シグネチャ:func (iv *IterableValue) GetString(key string) string
文字列値を取得します。
name := item.GetString("name")GetInt
シグネチャ:func (iv *IterableValue) GetInt(key string) int
整数値を取得します。
age := item.GetInt("age")GetFloat64
シグネチャ:func (iv *IterableValue) GetFloat64(key string) float64
浮動小数点値を取得します。
price := item.GetFloat64("price")GetBool
シグネチャ:func (iv *IterableValue) GetBool(key string) bool
ブール値を取得します。
enabled := item.GetBool("enabled")GetArray
シグネチャ:func (iv *IterableValue) GetArray(key string) []any
配列値を取得します。
items := item.GetArray("items")GetObject
シグネチャ:func (iv *IterableValue) GetObject(key string) map[string]any
オブジェクト値を取得します。
profile := item.GetObject("profile")GetWithDefault
シグネチャ:func (iv *IterableValue) GetWithDefault(key string, defaultValue any) any
値を取得し、キーが存在しない場合はデフォルト値を返します。
// オプションフィールドの取得、欠落時はデフォルト値を使用
timeout := item.GetWithDefault("timeout", 30)
mode := item.GetWithDefault("mode", "default")GetStringWithDefault
シグネチャ:func (iv *IterableValue) GetStringWithDefault(key string, defaultValue string) string
文字列値を取得し、キーが存在しない場合はデフォルト値を返します。
name := item.GetStringWithDefault("name", "不明")GetIntWithDefault
シグネチャ:func (iv *IterableValue) GetIntWithDefault(key string, defaultValue int) int
整数値を取得し、キーが存在しない場合はデフォルト値を返します。
age := item.GetIntWithDefault("age", 0)
port := item.GetIntWithDefault("port", 8080)GetFloat64WithDefault
シグネチャ:func (iv *IterableValue) GetFloat64WithDefault(key string, defaultValue float64) float64
浮動小数点値を取得し、キーが存在しない場合はデフォルト値を返します。
price := item.GetFloat64WithDefault("price", 0.0)
rate := item.GetFloat64WithDefault("rate", 1.0)GetBoolWithDefault
シグネチャ:func (iv *IterableValue) GetBoolWithDefault(key string, defaultValue bool) bool
ブール値を取得し、キーが存在しない場合はデフォルト値を返します。
enabled := item.GetBoolWithDefault("enabled", false)
debug := item.GetBoolWithDefault("debug", true)Exists
シグネチャ:func (iv *IterableValue) Exists(key string) bool
指定されたキーが存在するかチェックします。
if item.Exists("email") {
email := item.GetString("email")
fmt.Printf("メール: %s\n", email)
}ForeachNested
シグネチャ:func (iv *IterableValue) ForeachNested(path string, fn func(key any, item *IterableValue))
指定パス配下のネスト構造を再帰的に走査します。
IsNullData
シグネチャ:func (iv *IterableValue) IsNullData() bool
値全体が null かチェックします。
if item.IsNullData() {
fmt.Println("値は null です")
}IsNull
シグネチャ:func (iv *IterableValue) IsNull(key string) bool
指定されたキーの値が null かチェックします。
if item.IsNull("optional_field") {
fmt.Println("オプションフィールドは null です")
}IsEmptyData
シグネチャ:func (iv *IterableValue) IsEmptyData() bool
値全体が空かチェックします(nil、空文字列、空配列、空オブジェクト)。
if item.IsEmptyData() {
fmt.Println("値は空です")
}IsEmpty
シグネチャ:func (iv *IterableValue) IsEmpty(key string) bool
指定されたキーの値が空かチェックします。
if item.IsEmpty("tags") {
fmt.Println("タグリストは空です")
}Break
シグネチャ:func (iv *IterableValue) Break() error
反復停止のシグナルを返します。反復コールバック内で呼び出すと走査を早期終了できます。
// 注意:Break() は、コールバックが error を返す反復関数(ForeachWithError、
// ForeachNestedWithError など)でのみ有効です。通常の Foreach コールバックは
// error を返さないため、その中で item.Break() を呼び出しても反復は停止しません。
err := json.ForeachNestedWithError(data, func(key any, item *json.IterableValue) error {
if item.GetString("status") == "stop" {
// ターゲットを見つけたら反復を停止
return item.Break()
}
// 処理を継続
return nil
})Release
シグネチャ:func (iv *IterableValue) Release()
IterableValue をオブジェクトプールに返却し、内部データの参照を解放します。
json.Foreach(data, func(key any, item *json.IterableValue) {
// データ処理...
fmt.Println(item.GetData())
// 処理完了後に解放、GC 負荷を軽減
item.Release()
})StreamIterator 型
StreamIterator はメモリ効率の良いストリーミング反復を提供し、大型 JSON 配列に適しています。要素ごとに処理し、配列全体をメモリにロードする必要はありません。
NewStreamIterator
シグネチャ:func NewStreamIterator(reader io.Reader, cfg ...Config) *StreamIterator
ストリーミングイテレータを作成します。Config.BufferSize でバッファサイズを設定します。
file, _ := os.Open("large-array.json")
defer file.Close()
// 設定なし
it := json.NewStreamIterator(file)
for it.Next() {
val := it.Value()
fmt.Printf("インデックス %d: %v\n", it.Index(), val)
}
if err := it.Err(); err != nil {
panic(err)
}
// 設定あり
cfg := json.DefaultConfig()
cfg.BufferSize = 64 * 1024 // 64KB バッファ
it2 := json.NewStreamIterator(file, cfg)メソッド
| メソッド | シグネチャ | 説明 |
|---|---|---|
Next | func (si *StreamIterator) Next() bool | 次の要素に進む |
Value | func (si *StreamIterator) Value() any | 現在の要素を返す |
Index | func (si *StreamIterator) Index() int | 現在のインデックスを返す |
Err | func (si *StreamIterator) Err() error | 反復中のエラーを返す |
StreamObjectIterator 型
StreamObjectIterator はメモリ効率の良いストリーミング反復を提供し、大型 JSON オブジェクトに適しています。
NewStreamObjectIterator
シグネチャ:func NewStreamObjectIterator(reader io.Reader, cfg ...Config) *StreamObjectIterator
ストリーミングオブジェクトイテレータを作成します。
file, _ := os.Open("large-object.json")
defer file.Close()
it := json.NewStreamObjectIterator(file)
for it.Next() {
fmt.Printf("キー: %s, 値: %v\n", it.Key(), it.Value())
}
if err := it.Err(); err != nil {
panic(err)
}メソッド
| メソッド | シグネチャ | 説明 |
|---|---|---|
Next | func (soi *StreamObjectIterator) Next() bool | 次のキー・値ペアに進む |
Key | func (soi *StreamObjectIterator) Key() string | 現在のキーを返す |
Value | func (soi *StreamObjectIterator) Value() any | 現在の値を返す |
Err | func (soi *StreamObjectIterator) Err() error | 反復中のエラーを返す |
BatchIterator 型
BatchIterator は大型配列の効率的なバッチ処理に使用し、単一要素処理のオーバーヘッドを削減します。
NewBatchIterator
シグネチャ:func NewBatchIterator(data []any, cfg ...Config) *BatchIterator
バッチイテレータを作成します。Config.MaxBatchSize でバッチサイズを設定します。
data := make([]any, 10000)
// データの充填...
cfg := json.DefaultConfig()
cfg.MaxBatchSize = 100 // 1 バッチあたり 100 要素
it := json.NewBatchIterator(data, cfg)
for it.HasNext() {
batch := it.NextBatch()
// バッチ処理
processBatch(batch)
fmt.Printf("%d 個の要素を処理、残り %d\n", len(batch), it.Remaining())
}メソッド
| メソッド | シグネチャ | 説明 |
|---|---|---|
NextBatch | func (it *BatchIterator) NextBatch() []any | 次のバッチの要素を返す |
HasNext | func (it *BatchIterator) HasNext() bool | 次のバッチがあるかチェック |
Reset | func (it *BatchIterator) Reset() | イテレータを開始位置にリセット |
TotalBatches | func (it *BatchIterator) TotalBatches() int | 総バッチ数を返す |
CurrentIndex | func (it *BatchIterator) CurrentIndex() int | 現在の位置を返す |
Remaining | func (it *BatchIterator) Remaining() int | 残りの要素数を返す |
ParallelIterator 型
ParallelIterator は配列の並列処理に使用し、マルチコア CPU を活用して処理を高速化します。
NewParallelIterator
シグネチャ:func NewParallelIterator(data []any, cfg ...Config) *ParallelIterator
並列イテレータを作成します。Config.MaxConcurrency でワーカーゴルーチン数を設定します。
data := make([]any, 10000)
// データの充填...
cfg := json.DefaultConfig()
cfg.MaxConcurrency = 8 // 8 ワーカーゴルーチン
it := json.NewParallelIterator(data, cfg)
err := it.ForEach(func(idx int, val any) error {
// 各要素を並列処理
return processItem(idx, val)
})
if err != nil {
panic(err)
}ForEach
シグネチャ:func (it *ParallelIterator) ForEach(fn func(int, any) error) error
各要素を並列処理し、最初に遭遇したエラーを返します。
err := it.ForEach(func(idx int, val any) error {
// この関数は複数のゴルーチンで並列実行される
return nil
})ForEachWithContext
シグネチャ:func (it *ParallelIterator) ForEachWithContext(ctx context.Context, fn func(int, any) error) error
コンテキスト付きの並列処理。キャンセル操作をサポートします。
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err := it.ForEachWithContext(ctx, func(idx int, val any) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
return processItem(idx, val)
}
})ForEachBatch
シグネチャ:func (it *ParallelIterator) ForEachBatch(batchSize int, fn func(int, []any) error) error
並列バッチ処理です。
err := it.ForEachBatch(100, func(batchIdx int, batch []any) error {
// 各バッチは 1 つのゴルーチンで処理
return processBatch(batchIdx, batch)
})ForEachBatchWithContext
シグネチャ:func (it *ParallelIterator) ForEachBatchWithContext(ctx context.Context, batchSize int, fn func(int, []any) error) error
コンテキスト付きの並列バッチ処理です。
Map
シグネチャ:func (it *ParallelIterator) Map(transform func(int, any) (any, error)) ([]any, error)
各要素を並列変換し、新しいスライスを返します。
results, err := it.Map(func(idx int, val any) (any, error) {
if num, ok := val.(float64); ok {
return num * 2, nil
}
return nil, fmt.Errorf("unexpected type at index %d", idx)
})Filter
シグネチャ:func (it *ParallelIterator) Filter(predicate func(int, any) bool) []any
要素を並列フィルタリングし、条件を満たす要素のスライスを返します。
even := it.Filter(func(idx int, val any) bool {
if num, ok := val.(float64); ok {
return int(num)%2 == 0
}
return false
})Close
シグネチャ:func (it *ParallelIterator) Close()
ParallelIterator のリソースを解放します。
it := json.NewParallelIterator(data, cfg)
defer it.Close()完全なサンプル
大ファイルのストリーミング処理
package main
import (
"fmt"
"os"
"github.com/cybergodev/json"
)
func main() {
file, err := os.Open("large-array.json")
if err != nil {
panic(err)
}
defer file.Close()
it := json.NewStreamIterator(file)
count := 0
for it.Next() {
val := it.Value()
// 要素ごとに処理、メモリフレンドリー
count++
if count%1000 == 0 {
fmt.Printf("%d 個の要素を処理済み、現在の値: %v\n", count, val)
}
}
if err := it.Err(); err != nil {
panic(err)
}
fmt.Printf("合計 %d 個の要素を処理\n", count)
}並列処理
package main
import (
"fmt"
"sync/atomic"
"github.com/cybergodev/json"
)
func main() {
// JSON 配列のパース
data := `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`
var arr []any
json.Unmarshal([]byte(data), &arr)
// 並列イテレータの作成(4 ワーカーゴルーチン)
cfg := json.DefaultConfig()
cfg.MaxConcurrency = 4
it := json.NewParallelIterator(arr, cfg)
var sum int64
err := it.ForEach(func(idx int, val any) error {
if num, ok := val.(float64); ok {
atomic.AddInt64(&sum, int64(num))
}
return nil
})
if err != nil {
panic(err)
}
fmt.Printf("合計:%d\n", sum) // 出力:合計:55
}バッチ処理
package main
import (
"fmt"
"github.com/cybergodev/json"
)
func main() {
// 大規模データセットの作成
data := make([]any, 1000)
for i := range data {
data[i] = map[string]any{"id": i, "value": i * 10}
}
// 1 バッチあたり 100 要素
cfg := json.DefaultConfig()
cfg.MaxBatchSize = 100
it := json.NewBatchIterator(data, cfg)
batchNum := 0
for it.HasNext() {
batch := it.NextBatch()
batchNum++
// バッチ処理(データベースへの一括書き込みなど)
fmt.Printf("バッチ %d: %d 個の要素を処理\n", batchNum, len(batch))
}
fmt.Printf("総バッチ数:%d\n", it.TotalBatches())
}Iterator の再利用
package main
import (
"fmt"
"github.com/cybergodev/json"
)
func main() {
// 初回走査
it := json.NewIterator([]any{"a", "b", "c"})
for it.HasNext() {
val, _ := it.Next()
fmt.Println(val)
}
// 同一イテレータを再利用して新しいデータを走査、再割り当てを回避
it.ResetWith([]any{1, 2, 3, 4})
for it.HasNext() {
val, _ := it.Next()
fmt.Println(val)
}
}パフォーマンスのアドバイス
- Iterator の再利用 -
Reset/ResetWithで再割り当てを回避、複数回走査する場面に適しています - 大規模データセットにはストリーミングイテレータを使用 -
StreamIterator/StreamObjectIteratorは要素ごとに処理し、メモリフレンドリーです - バッチ処理でオーバーヘッドを削減 -
BatchIteratorはバッチ単位で処理し、単一要素のオーバーヘッドを下げます - CPU 集約的なタスクは並列処理 -
ParallelIteratorでマルチコアを活用して高速化します - IterableValue を解放 -
Foreachコールバック内で処理完了後にRelease()を呼び出し、GC 負荷を軽減します
関連
- パッケージレベル反復関数 - Foreach/ForeachFile などの反復関数
- Processor 反復メソッド - 対応するプロセッサ反復メソッド
- 大ファイル処理 - 大ファイル処理ガイドと API リファレンス
- NDJSON プロセッサ - JSONL 処理