Goで配列操作をラップする!JavaScriptライクなArrayメソッドを実現するパッケージを開発してみた
はじめに
Go言語で配列やスライスを操作する際、標準ライブラリではシンプルな方法が提供されています。しかし、複雑な処理を行うときには多くのコードを書かなければならず、可読性や開発効率が落ちる場合があります。
JavaScriptのArrayメソッド(map, filter, reduce, find, some など)は直感的で強力ですが、Goにはそのような高レベルの操作を簡単に実現する仕組みがありません。
そこで、JavaScriptの配列メソッドと同じ感覚で操作できるGoパッケージを開発しました!この記事では、このパッケージの特徴や使い方について紹介します。
パッケージ開発の背景
Goのシンプルな配列操作に対する課題として、繰り返し処理や条件付き抽出を毎回手書きするのが面倒だったことが挙げられます。一部のライブラリは提供されていますが、汎用性や直感的なインターフェースに欠ける場合が多いです。
そのため、JavaScriptのArrayメソッドが非常に使いやすいと感じていた私は、Goでも同様の感覚で操作できるようにしたいと考え、このパッケージを開発しました。
このパッケージの特徴
Go 1.18で導入されたジェネリクスを活用しています。これにより、型を指定して安全に配列操作ができ、異なる型の配列にも汎用的に対応可能です。
シンプルなインターフェース
map, filter, reduce などの関数をスライス型に関連付けたメソッドとして利用可能です。
可読性の向上
一連の配列操作をチェーン可能にすることで、より簡潔で直感的なコードを書けるようになります。
使い方
パッケージをインストールするには以下を実行してください。
go get github.com/hiroky1983/array-method
次に、プロジェクトでパッケージをインポートします。
import "github.com/hiroky1983/array-method/array"
importしたarray
パッケージから各、メソッドを呼び出します。
メソッドによって異なりますが、基本的に
- 第一引数に基となる配列
- 第二引数に関数を処理する条件
を記述します。
以下はこのパッケージを使ったサンプルコードです。
package main
import (
"fmt"
"github.com/hiroky1983/array-method"
)
func main() {
arr := []int{1, 2, 3, 4, 5}
mapped := array.Map(arr, func(v int) int {
return v * 3
})
fmt.Println("Mapped:", mapped) // Output: [3 6 9 12 15]
}
実装されているメソッドの紹介
Map
: スライスの各要素に関数を適用して新しいスライスを生成します。
Filter
: 条件を満たす要素のみを含む新しいスライスを生成します。
Reduce
: スライスの要素を累積的に処理し、1つの値にまとめます。
Find
: 条件を満たす最初の要素を返します。条件を満たす要素がない場合は、nilを返します。
FindIndex
: 条件を満たす最初の要素のインデックスを返します。条件を満たす要素がない場合は、-1を返します。
ForEach
: スライスの各要素に対して、指定された処理を順次実行します。
Some
: スライス内に条件を満たす要素が1つでも存在する場合にtrueを返します。
sample struct
デバッグ用のサンプル構造体を定義する
type Person struct {
Name string
Age int
}
type PersonPointer struct {
Name *string
Age *int
}
type NewPerson struct {
Person Person
IsAdult bool
}
Filter
条件に一致する要素だけを抽出して新しい配列を返すメソッドです。
function interface
Filter[T any](slice []T, condition func(T) bool) []
evenNumbers := array.Filter(nums, func(n int) bool {
return n%2 == 0
})
fmt.Println(evenNumbers) // Output: [{{Alice 25} true} {{Bob 30} true} {{Charlie 15} false} {{David 18} false} {{Eve 21} true}]
Map
配列の各要素に関数を適用して、新しい配列を作成します。
function interface
Map[Input any, Output any](slice []Input, transform func(Input) Output) []Output
nums := []int{1, 2, 3, 4, 5}
doubled := array.Map(nums, func(n int) int {
return n * 2
})
fmt.Println(doubled) // Output: [2 4 6 8 10]
Find
条件に一致する最初の要素を検索します。
function interface
Find[T any](slice []T, condition func(T) bool) *T
people := []Person{
{"Alice", 25},
{"Bob", 30},
}
person := array.Find(people, func(p Person) bool {
return p.Name == "Alice"
})
fmt.Println(person) // Output: &{Alice 25}
FindIndex
条件に一致する最初の要素のインデックスを検索します。
function interface
FindIndex[T any](slice []T, condition func(T) bool) int
people := []Person{
{"Alice", 25},
{"Bob", 30},
}
index := array.FindIndex(people, func(p Person) bool {
return p.Name == "Bob"
})
fmt.Println(index) // Output: 1
ForEach
配列の各要素に対してアクションを実行します。
function interface
ForEach[T any](slice []T, callback func(T))
people := []Person{
{"Alice", 25},
{"Bob", 30},
}
array.ForEach(people, func(p Person) {
fmt.Println(p.Name)
})
// Output: Alice Bob
Reduce
配列の要素を累積して一つの値を生成します。
function interface
Reduce[T any, U any](slice []T, reducer func(U, T) U, initial U) U
nums := []int{1, 2, 3, 4, 5}
sum := array.Reduce(nums, func(prev int, current int) int {
return prev + current
}, 0)
fmt.Println(sum) // Output: 15
Some
少なくとも一つの要素が条件を満たすかどうかを確認します。
function interface
Some[T any](slice []T, condition func(T) bool) bool
nums := []int{1, 2, 3, 4, 5}
result := array.Some(nums, func(n int) bool {
return n%2 == 0
})
fmt.Println(result) // Output: true
おわりに
このパッケージを利用することで、GoでもJavaScriptのように直感的に配列を操作できるようになります。ぜひこのパッケージを試してみて、フィードバックをいただければ幸いです!
GitHubリポジトリはこちら
Go packages
開発についての補足
このパッケージは個人開発のプロジェクトで、現在も機能の追加や改修を積極的に行っています。
本来、jsでは第二引数でindexが取れるのですが、それが取れなかったりするので今後アップデートしていきます。
今後のアップデートでは、さらに多くの配列操作メソッドやユースケースに対応する予定です。ご意見やフィードバックをいただければ、機能拡充の参考にさせていただきます。
Discussion
ご存知でしたら申し訳ありません。こちらのloというライブラリが今後の開発に役立つと思います!
おお、既に存在したのですね!
ありがとうございます!
参考にさせていただきます。