こんにちは。Tomoyuki(@tomoyuki65)です。
Go言語(Golang)のバージョン1.27では、ジェネリックメソッドが追加され、これまで関数ではできていた型パラメータの宣言が、メソッド自身でもできるようになりました。
この記事では、そんなジェネリックメソッドの使い方についてご紹介します。
Go言語(Golang)1.27で追加されたジェネリックメソッドの使い方を紹介!
例えば任意の型を持てるような独自のリスト型を定義し、それに任意の型に変換処理させるメソッド「Convert」を作る場合は以下の通りです。
package main
import (
"fmt"
)
// 任意の型(ここではEとする)を持てるリスト型を定義
type List[E any] []E
// 型変換するためのジェネリックメソッド(パラメータに型変換用の関数を渡す)
func (l List[E]) Convert[R any](f func(E) R) List[R] {
result := make(List[R], len(l))
// パラメータの関数fを利用して型変換処理
for i, value := range l {
result[i] = f(value)
}
return result
}
func main() {
// int型のリストを設定
listInt := List[int]{1, 2, 3}
// int型のリストをstring型のリストへ変換
listString := listInt.Convert(func(num int) string {
return fmt.Sprintf("%d", num)
})
// ログ出力
fmt.Printf("%q\n", listString)
fmt.Printf("%T\n", listString)
}
※上記のConvertメソッドの利用について、パラメータに指定する関数の戻り値で型推論できるので「listInt.Convert(func(num int) string {}」と記載しているが、明示的に型定義する場合は「listInt.Convert[string](func(num int) string {}」と書くこともできます。
実行結果
["1" "2" "3"]
main.List[string]
このように、Go1.27ではメソッド自身に対して型パラメータの宣言ができるようになっています。
Go1.26以前の場合は?
例えば上記のサンプルコードをGo1.26以前で実現させたい場合、ジェネリックメソッドが使えなかったため、型変換処理については以下のようにジェネリック関数を使って定義する必要がありました。
// ジェネリック関数として定義
func Convert[E any, R any](l List[E], f func(E) R) List[R] {
result := make(List[R], len(l))
for i, value := range l {
result[i] = f(value)
}
return result
}
「math/rand/v2」パッケージにジェネリックなNメソッドが追加
他の例としては、「math/rand/v2」パッケージにジェネリックなNメソッドが追加されており、サンプルコードとしては以下の通りです。
package main
import (
"fmt"
"math/rand/v2"
"time"
)
func main() {
// 乱数生成器を作成
r := rand.New(rand.NewPCG(1, 2))
// int型の値を生成
n1 := r.N(100)
fmt.Printf("%d (%T)\n", n1, n1)
// int64型の値を生成
n2 := r.N(int64(100))
fmt.Printf("%d (%T)\n", n2, n2)
// time.Duration型の値を生成
d := r.N(5 * time.Second)
fmt.Printf("%v (%T)\n", d, d)
}
実行結果の例
76 (int)
61 (int64)
3.922140008s (time.Duration)
ジェネリックメソッドに関する注意点
そんなジェネリックメソッドについては、独自に定義した型や構造体のメソッドとして利用できますが、interfaceのメソッドとしては利用できないので注意しましょう。
例えば、APIを設計する際にinterfaceを利用して処理を抽象化することがありますが、そういったケースではジェネリックメソッドを利用できません。
そのため、現状の使い所としては、独自に定義した型や構造体に対して、何らかの処理を行うメソッドを作る際に利用する可能性があります。
最後に
今回はGo1.27で追加されたジェネリックメソッドの使い方についてご紹介しました。
何らかの処理でジェネリクスを使いたい場合、これまでは個別にジェネリック関数として切り出す必要がありましたが、Go 1.27からは独自に定義した型や構造体に対して、ジェネリックメソッドを定義できるようになりました。
利用する機会は多くありませんが、ジェネリクスを使う際の選択肢が増えたので覚えておきましょう。




コメント