devlog

【Go】slices.Contains() のソースコードを見てみる

2023-06-05

こんにちは。Goの話です。

Goのスライスでは map や filter といった関数型チックな書き方ができません。そのためコード量が多くなってしまい悶々としていたのですが、Go1.18で golang.org/x/exp/slices が用意されました。スライスを楽に扱えます。

今回は、そのソースコードを見ていきます。具体的には slices.Contains() という関数を取り上げます。

slices.Contains()

slices.Contains() は、要素の存在チェックをします。例えば次のように書きます。

import ( "golang.org/x/exp/slices" ) func main() { list := []string{"orange", "apple", "blueberry"} if slices.Contains(list, "orange") { // 存在する } }

slices.Contains() のソースコードを見る

ソースコードはこちらです。

func Contains[E comparable](s []E, v E) bool { return Index(s, v) >= 0 }

まず入出力ですが、ジェネリクスができます。型制約は comparable です。雑に言うと「比較できるもの」でしょうか。例えばstringやintが該当します。他にも沢山あるので詳しくはドキュメントをご覧ください。

さて、処理としては slices.Index() を呼んでます。

slices.Index() のソースコードを見る

func Index[E comparable](s []E, v E) int { for i := range s { if v == s[i] { return i } } return -1 }

slices.Index() もジェネリクスを使えます。同じく型制約は comparable です。

さて、処理内容ですがシンプルですね。スライスをループし、要素を見つけ次第 index を返します。存在しなかったら -1 を返します。

あるあるなコードだと思いました。

slices.IndexFunc() のソースコードを見る

ついでに見てみます。

func IndexFunc[E any](s []E, f func(E) bool) int { for i := range s { if f(s[i]) { // ここが違う return i }

slices.IndexFunc() は判定処理をカスタマイズできます。jsで言うと Array.prototype.findIndex() に相当するでしょうか。

ソースコードを見れば slices.Index() との違いがよく分かります。関係ないですが、Goはドキュメントにソースコードへのリンクが貼ってあるところが良いですね。親しみやすさを感じます。

Links

  • 作成日
    2023-06-05
  • 更新日
    2023-12-26