Go1.21で追加された「slicesパッケージ」とは?実際にパッケージ内の関数を使うコードを書いてみた。
最近になって開発中のプロジェクトのGoのバージョンが1.21になったので、新しく追加された機能について調べようと思い、今回はslicesパッケージについて調べてみました。
slicesパッケージの概要
Package slices defines various functions useful with slices of any type.
とパッケージのドキュメントに書かれているように、slicesパッケージは、あらゆる型のスライスに対して役立つ関数を提供しているパッケージのようです。ジェネリクスを利用して実装されており、あまり型のことを気にせずに使用できそうです。
slicesパッケージの関数
Clip | スライスから使われていないキャパシティを取り除いたスライスを返します。 |
---|---|
Contains | スライスに特定の要素が含まれているかを判定します。 |
Delete | スライスの指定した位置の要素を削除します。 |
Equal | 渡された二つのスライスが等しいかを判定します。 |
Index | スライスに特定の要素がどの位置にあるかを数値で返します。 |
Insert | スライスの指定した位置に指定した要素を挿入します。 |
IsSorted | スライスが昇順でソートされているかを判定します。 |
Max | スライス内で最も大きい要素を返します。 |
Min | スライス内で最も小さい要素を返します。 |
Replace | スライスの指定した位置の要素を、指定した要素に入れ替えたスライスを返します。 |
Reverse | スライス内の順番を反転します。 |
Sort | スライスを昇順でソートします。 |
SortFunc | スライスを、引数に渡した関数を基に昇順でソートします。 |
slicesパッケージの関数の使用例
上で挙げた関数を使ったコードを実際にいくつか書いてみます。
Delete
season := []string{"Spring", "Summer", "Autumn", "Winter"}
season = slices.Delete(season, 1, 3)
fmt.Println(season) // [Spring Winter]
// slicesパッケージを使わない場合
season = []string{"Spring", "Summer", "Autumn", "Winter"}
season = append(season[:1], season[3])
fmt.Println(season) // [Spring Winter]
append
を使った従来の方法よりもシンプルで、読んでいても分かりやすいコードになったと思います。マップのdelete
とは違い、返り値のスライスを利用するようです。
Insert
season := []string{"Spring", "Summer", "Winter"}
season = slices.Insert(season, 2, "Autumn")
fmt.Println(season) // [Spring Summer Autumn Winter]
// 複数の要素を挿入可能
season = []string{"Sunday", "Monday", "Tuesday", "Friday", "Saturday"}
season = slices.Insert(season, 3, "Wednesday", "Thursday")
fmt.Println(season) // [Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
// slicesパッケージを使わない場合
season = []string{"Spring", "Summer", "Winter"}
season = append(season[:2], "Autumn", season[2])
fmt.Println(season) // [Spring Summer Autumn Winter]
これもappend
を使う従来の方法よりも直感的でわかりやすいコードになったと思います。
Replace
season := []string{"Spring", "夏", "秋", "Winter"}
season = slices.Replace(season, 1, 3, "Summer", "Autumn")
fmt.Println(season) // [Spring Summer Autumn Winter]
// slicesパッケージを使わない場合
season = []string{"Spring", "夏", "秋", "Winter"}
season = append(season[:1], "Summer", "Autumn", season[3])
fmt.Println(season) // [Spring Summer Autumn Winter]
Replace
は、上記のDelete
とInsert
を続けて行うような関数です。
Sort
numbers := []int{1, 3, 5, 2, 100, 50}
slices.Sort(numbers)
fmt.Println(numbers) // [1 2 3 5 50 100]
// slicesパッケージを使わない場合
numbers = []int{1, 3, 5, 2, 100, 50}
sort.Ints(numbers)
fmt.Println(numbers) // [1 2 3 5 50 100]
降順でソートしたい場合は、ソート後にReverse
という関数を使えば実装できます。
SortFunc
type Person struct {
name string
age int
}
p1 := Person{"Alice", 25}
p2 := Person{"Vera", 10}
p3 := Person{"Bob", 40}
p4 := Person{"Alice", 15}
persons := []Person{p1, p2, p3, p4}
fmt.Println(persons) // [{Alice 25} {Vera 10} {Bob 40} {Alice 15}]
slices.SortFunc(persons, func(a, b Person) int {
if n := cmp.Compare(a.name, b.name); n != 0 {
return n
}
return cmp.Compare(a.age, b.age)
})
fmt.Println(persons) // [{Alice 15} {Alice 25} {Bob 40} {Vera 10}]
// slicesパッケージを使わない場合
persons = []Person{p1, p2, p3, p4}
fmt.Println(persons) // [{Alice 25} {Vera 10} {Bob 40} {Alice 15}]
sort.Slice(persons, func(i, j int) bool {
if persons[i].name == persons[j].name {
return persons[i].age < persons[j].age
}
return persons[i].name < persons[j].name
})
fmt.Println(persons) // [{Alice 15} {Alice 25} {Bob 40} {Vera 10}]
SortFunc
を使えば、様々な条件のソートを実装できます。上記のコードでは、名前順でソートし、名前で比較して違いがなければ、年齢でソートする、といった条件のソートを実装しました。
さいごに
Go1.21で新たに追加されたパッケージの中からslices
パッケージについて調べてみました。上でも書いたように、従来よりも直感的でわかりやすいコードを書けるようになっていると思います。また、slicesパッケージにあるSort
関数と同じような機能は、以前からあるsort
パッケージの関数にもありますが、現在はそれらの関数のドキュメントに、
Note: consider using the newer slices.Sort function, which runs faster.
などと書かれ、slices
パッケージの使用を推奨しています。なのでこれからスライスを操作するようなコードを書くときはまずこちらのslices
パッケージの使用を検討しましょう。
この記事を書いた人
-
これまで農業、士業と経験し、まったく異業種のエンジニアとしてアーティスに入社。
現在は事業開発部でバックエンドエンジニアとして仕事に従事。可読性の高いコードが書けるよう日々勉強中。趣味は一人旅。
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー