go の配列操作ライブラリを探す

go でそれなりに複雑なロジックを実装する時に欲しくなってくるのが配列操作ライブラリ。 何でも for でやるのが go way なのかもしれませんが、XXX.filter(...).map(...) とかやりたいですよね。 lodash みたいなのはないかと思って探してみたところ、一応いくつかあるみたいでした。

が、どれもリフレクションを使う必要があったり、コードを自動生成したりで、イマイチでした。 今のところ generics がないのでしょうがないかもしれないですが、 さらに探してみたところ、 go-linq というライブラリを見つけました。 LINQ は元々 C# などで使えたもので、それの Go 版みたいです。 これが type assersions を使う事なく使えるみたいなので試してみました。

package main

import (
    "fmt"

    linq "github.com/ahmetb/go-linq"
)

type MyNum struct {
    Num int
}

func main() {

    // MyNum のスライスを生成
    var nums []MyNum
    linq.Range(1, 5).
    SelectT(func (num int) MyNum {
        return MyNum{Num: num}
    }).
    ToSlice(&nums) // <- 変数に直接入れられる!!

    // いつもの偶数二乗和
    var result MyNum
    result = linq.From(nums).
    WhereT(func (myNum MyNum) bool { // <- 引数が interface{} でなくていい!!
        // 偶数のみ抽出
        return myNum.Num % 2 == 0
    }).
    SelectT(func (myNum MyNum) MyNum { // <- 戻り値も interface{} でなくていい!!
        // 二乗する
        num := myNum.Num
        return MyNum{Num: num * num}
    }).
    AggregateT(func (acc, myNum MyNum) MyNum {
        // 合計する
        return MyNum{Num: acc.Num + myNum.Num}
    }).(MyNum) // Aggregate の返り値は type assersion 必要みたい。おしい

    fmt.Printf("%#v\n", result) // -> main.MyNum{Num:20}
    fmt.Printf("%#v\n", result.Num) // -> 20
}

なかなかよさそうですね。

  • map -> Select
  • filter -> Where
  • reduce -> Aggregate

と名前はちょっと違うものの、当面これを使ってみます。