Open1
Goのジェネリクス導入の背景について

Go のジェネリクス導入の背景
Go2としてエラーハンドリングと一緒に提案されたみたい
issue だと 2016 年が最初
公式の記事は 2018 年
ここに詳しくあるらしい
2022年の 1.18 でリリース
- モチベーションは型の詳細を抽象化したいこと
- []byte と string の両方を操作できるような関数を用意すること
-
C++, Java の教訓を活かしたかったため、導入に慎重だった
- コンパイラが明確なエラーを返すようにするとか
Goのジェネリクスにおいて、どのようにインスタンス化されるのか
mattn さんの記事を参考にした
- Java型は実装は1つ
- C++型はパラメータとして渡された型の分だけ実装
- GoはC++型
- ジェネリック型のリフレクション情報に、コンパイル時の型情報が含まれている
- 共変、反変はない
C++のジェネリクスのコンパイル
コンパイラはテンプレートのコードに型を適用し、具体的な型に対する専用のコードを生成
template<typename T>
void print(T x) { std::cout << x << std::endl; }
int main() {
print<int>(42); // テンプレートを int でインスタンス化
print<double>(3.14); // テンプレートを double でインスタンス化
}
Goのジェネリクスのコンパイル
コンパイラはインスタンス化時に型パラメータを具体的な型に置き換え、型チェックを行う。
C++同様、型情報はコンパイル時に解決される。生成されるコードは異なる。
func Print[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
func main() {
Print([]int{1, 2, 3}) // T を int に推論・インスタンス化
}
インタフェースとの違い