冬のセール!
Iterator

Iterator を Go で

Iterator 振る舞いに関するデザインパターンの一つで 複雑なデータ構造の内部の詳細を公開することなく 順次横断的に探索することを可能とします

Iterator のおかげで クライアントは 異なるコレクション上の要素の探索を 単一のイテレーター・インターフェースを使用して同様の方法で行えます

概念的な例

Iterator パターンの基本的な考え方は コレクションの反復ロジックをイテレーターと呼ばれる別のオブジェクトに抽出することです このイテレーターは 型から独立した コレクション上の反復を行う一般的メソッドを提供します

collection.go: コレクション

package main

type Collection interface {
	createIterator() Iterator
}

userCollection.go: 具象コレクション

package main

type UserCollection struct {
	users []*User
}

func (u *UserCollection) createIterator() Iterator {
	return &UserIterator{
		users: u.users,
	}
}

iterator.go: イテレーター

package main

type Iterator interface {
	hasNext() bool
	getNext() *User
}

userIterator.go: 具象イテレーター

package main

type UserIterator struct {
	index int
	users []*User
}

func (u *UserIterator) hasNext() bool {
	if u.index < len(u.users) {
		return true
	}
	return false

}
func (u *UserIterator) getNext() *User {
	if u.hasNext() {
		user := u.users[u.index]
		u.index++
		return user
	}
	return nil
}

user.go: クライアント・コード

package main

type User struct {
	name string
	age  int
}

main.go: クライアント・コード

package main

import "fmt"

func main() {

	user1 := &User{
		name: "a",
		age:  30,
	}
	user2 := &User{
		name: "b",
		age:  20,
	}

	userCollection := &UserCollection{
		users: []*User{user1, user2},
	}

	iterator := userCollection.createIterator()

	for iterator.hasNext() {
		user := iterator.getNext()
		fmt.Printf("User is %+v\n", user)
	}
}

output.txt: 実行結果

User is &{name:a age:30}
User is &{name:b age:20}

他言語での Iterator

Iterator を C# で Iterator を C++ で Iterator を Java で Iterator を PHP で Iterator を Python で Iterator を Ruby で Iterator を Rust で Iterator を Swift で Iterator を TypeScript で