Goの公式ブログは最近、GopherCon 2021での講演に基づいて、RobertGriesemerとIanLanceTaylorの2人の大物による新機能「ジェネリック」に関する記事を公開しました。
▲左:Go言語の設計者の1人であるRobert Griesemer、右:Goジェネリックの主な設計者であるIan Lance Taylor
ビデオアドレス:https ://www.youtube.com/watch?v = Pa_e9EeCdy8&t = 54s
少し前に正式にリリースされたGo1.18は、ジェネリックのサポートを追加しました。これは、Goがオープンソースになって以来最大の変更であると言われています。Genericsは、使用される特定の型に依存しないプログラミングパラダイムであり、関数と型の実装で型のコレクションから任意の型を使用できるようにします。
ジェネリックスは、Goに3つの新しい重要なことを追加します。
- 関数と型の「型パラメータ」
- インターフェイスタイプを、メソッドのないインターフェイスタイプを含む、タイプのコレクションとして定義します
- 型推論:ほとんどの場合、ジェネリック関数を呼び出すときに「型引数」を省略できます
タイプパラメータ
これで、関数と型の両方に型パラメーターがあります」。型パラメーターリストは、括弧の代わりに角かっこを使用することを除いて、通常のパラメーターリストのように見えます。
浮動小数点値の基本的な非ジェネリックMin関数から始めましょう。
func Min(x, y float64) float64 {
if x < y {
return x
}
return y
}
タイプパラメータリストを追加して、この関数をジェネリックにします。さまざまなタイプで機能するようにします。この例では、単一の型パラメーターを持つ型パラメーター・リストが追加されT
、置き換えられてfloat64
います。
import "golang.org/x/exp/constraints"
func GMin[T constraints.Ordered](x, y T) T {
if x < y {
return x
}
return y
}
この関数は、型引数を使用して呼び出すことができます。
x := GMin[int](2, 3)
GMin
タイプパラメータは、この場合はインスタンス化int
と呼ばれるに提供されます。インスタンス化は2つのステップで行われます。まず、コンパイラーは、ジェネリック関数またはジェネリック型のすべての型パラメーターをそれぞれの型引数に置き換えます。次に、コンパイラは、各型パラメータがそれぞれの制約を満たしていることを確認します。2番目のステップが失敗すると、インスタンス化は失敗し、プログラムは無効になります。
インスタンス化が成功すると、他の関数と同じように呼び出すことができる非ジェネリック関数が生成されます。例えば:
fmin := GMin[float64]
m := fmin(2.71, 3.14)
GMin[float64]
のインスタンス化により、Min
関数呼び出しで使用できる同等の関数が生成されます。タイプパラメータは、タイプでも使用できます。
type Tree[T interface{}] struct {
left, right *Tree[T]
value T
}
func (t *Tree[T]) Lookup(x T) *Tree[T] { ... }
var stringTree Tree[string]
上記の例では、ジェネリック型Tree
は型パラメーターの値を格納しますT
。この例のように、ジェネリック型にもメソッドを含めることができますLookup
。ジェネリック型を使用するには、インスタンス化する必要があります。これは、Tree[string]
型引数を使用したstring
インスタンス化の例ですTree
。