emahiro/b.log

日々の勉強の記録とか育児の記録とか。

Go1.18 の Generics を使ってみた話

Overview

Go 1.18 がリリースされて目玉の機能である Generics について一通り触ってみました。

github.com

実装に入門する

公式の Go の Genericsチュートリアルを参考に実装してみました。

go.dev

またより詳しい入門には以下の公式のブログがあります。

go.dev

サンプル実装

map の key を取り出す

ありがちな実装ですが map から key のみを取り出したり、value だけを取り出したり、といった処理を書くことができます。
今までは取り出した値の型ごと(int, string) に Keys だったり Values の実装が必要でしたが、これからは以下のようにかけます。

func Keys[T comparable](m map[T]interface{}) []T {
    keys := make([]T, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

簡単に再実装をしてみましたが、これは https://pkg.go.dev/golang.org/x/exp@v0.0.0-20220325121720-054d8573a5d8/maps#Keys に既に実装されてました。

スライスのシャッフル処理

func shuffle[T comparable](s []T) {
    rand.Seed(10) // seed は任意の自然数
    rand.Shuffle(len(s), func(i, j int) {
        s[i], s[j] = s[j], s[i]
    })
}

ref: https://go.dev/play/p/OToYELH1S-1

その他使えそうなユースケケースについて

以下でまとめたことがありましたが、API クライアントの共通化処理において Setter っぽい実装で Getter を書くというユースケースにおいては Generics を使うことができそうだなと思いました。

ema-hiro.hatenablog.com

golang.org/x/exp 配下のパッケージついて

今まで型ごとに冗長な実装をせざる得なかった、slice や map の操作については以下の2つの packages にまとまっています。

  • golang.org/x/exp/maps
  • golang.org/x/exp/slices

ありがちな sort なども slices パッケージに実装されています。

https://cs.opensource.google/go/x/exp/+/054d8573:slices/zsortordered.go;drc=054d8573a5d8a1df3b1d31df254b260a09c7ebe0;l=12

まとめ

以下のブログにある通り、これを使ってもっとゴリゴリコードを抽象化したり関数型っぽい実装が増えることもあるのかもしれませんが当面はユースケースを絞って適用していく、くらいのところでまずは留めておこうかなと思っています。特にプロダクションで書く場合には。

future-architect.github.io