Go 1.18でGenerics(ジェネリクス)が追加されました。
Genericsを利用すると「型が異なるだけで同じ処理をもつ複数の関数」を「1つの関数」として定義することができます。
ここでは、Generics(ジェネリクス)の基本的な使い方を確認します。
動作確認用コード
( Genericsを使わない )
まず、Genericsを使わない状態のコードです。型ごとに関数を用意しています。
package main
import (
"fmt"
)
func main() {
stringValue := "111"
intValue := 111
boolValue := false
fmt.Printf("sampleFuncString: %#v\n", sampleFuncString(stringValue))
fmt.Printf("sampleFuncInt: %#v\n", sampleFuncInt(intValue))
fmt.Printf("sampleFuncBool: %#v\n", sampleFuncBool(boolValue))
}
func sampleFuncString(x string) string {
return x
}
func sampleFuncInt(x int) int {
return x
}
func sampleFuncBool(x bool) bool {
return x
}
sampleFuncString: "111"
sampleFuncInt: 111
sampleFuncBool: false
Genericsの使い方
comparableで型制約
以下、先述のコードをGenericsを利用して1つの関数で実装してみました。
package main
import (
"fmt"
)
func main() {
stringValue := "111"
intValue := 111
boolValue := false
fmt.Printf("sampleFuncGenerics1: %#v\n", sampleFuncGenerics1(stringValue))
fmt.Printf("sampleFuncGenerics1: %#v\n", sampleFuncGenerics1(intValue))
fmt.Printf("sampleFuncGenerics1: %#v\n", sampleFuncGenerics1(boolValue))
}
func sampleFuncGenerics1[T comparable](x T) T {
return x
}
sampleFuncGenerics1: "111"
sampleFuncGenerics1: 111
sampleFuncGenerics1: false
comparable
は、型パラメータを制約したいときにだけ利用できます。
sampleFuncGenerics1
の引数に指定できる値ですが、 ==, !=演算子
で比較可能な値のみになります。
以下のように、スライスなどは ==演算子
で比較不可能なので利用できません。

複数の型で型制約
型パラメータを string
または int
だけに制約したい場合、以下のように実装できます。
package main
import (
"fmt"
)
func main() {
stringValue := "111"
intValue := 111
fmt.Printf("sampleFuncGenerics2: %#v\n", sampleFuncGenerics2(stringValue))
fmt.Printf("sampleFuncGenerics2: %#v\n", sampleFuncGenerics2(intValue))
}
func sampleFuncGenerics2[T string | int](x T) T {
return x
}
sampleFuncGenerics2: "111"
sampleFuncGenerics2: 111
独自インタフェースで型制約
型パラメータを string
または int
だけに制約したい場合、以下のようにインタフェースを定義して実装することも可能です。
package main
import (
"fmt"
)
func main() {
stringValue := "111"
intValue := 111
fmt.Printf("sampleFuncGenerics3: %#v\n", sampleFuncGenerics3(stringValue))
fmt.Printf("sampleFuncGenerics3: %#v\n", sampleFuncGenerics3(intValue))
}
type SampleType interface {
string | int
}
func sampleFuncGenerics3[T SampleType](x T) T {
return x
}
sampleFuncGenerics3: "111"
sampleFuncGenerics3: 111