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できること自体は、知っていると得かもしれませんよ。