Goでも独自型をrangeしたい!chanを使う
Pythonでは__iter__メソッドを定義すれば((Rubyでは.eachメソッドを定義してEnumerableをincludeすれば、C#ではGetEnumerator()メソッドを定義すれば、
PHPではIteratorを実装すれば))、
晴れて独自のコレクション型でも、foreach文などでループできるようになるわけですが、でもGoにはそんな仕組みはありません。
まあ、妥協案としては、関数を引数にとる.Eachを作ることはできます。
sum := 0
myCollection.Each(func(x int) {
sum += x
})
「でも、ぼくがつくったさいきょうの○○型をfor - range文で使いたいんだ!」
解法:channelを返す.Iter()
知ってる人は知っている、rangeにはchannelが渡せます。
A "for" statement with a "range" clause iterates through all entries of an array, slice, string or map, or values received on a channel.
he Go Programming Language Specification - The Go Programming Language
これを利用して、deckarep/golang-setのSet型は、for文で使えるように.Iter()メソッドを定義してます。
package main
import (
"fmt"
mapset "github.com/deckarep/golang-set"
)
func main() {
s := mapset.NewSet()
s.Add(7)
s.Add(11)
s.Add(13)
s.Add(11) // Setだから、重複は排除される
c := s.Iter()
fmt.Printf("%V\n", c) // %!V(<-chan interface {}=0xXXXXXXXXXX)
for x := range s.Iter() { // range文で使える!
fmt.Println(x)
}
// 7
// 11
// 13
}
やりましたね!
genericsが無いGolangで独自コレクションを作る機会は少ないでしょうけど、
channelがrangeできること自体は、知っていると得かもしれませんよ。