ジェネリクスメソッド (Go 1.27)
Go 1.27 で入った、メソッド自身が新しい型パラメータを宣言できる機能。提案は #77273 "A change of view."。
Go 1.26 まで、型パラメータを新しく宣言できるのは関数と型だけだった。 レシーバ由来の型パラメータは使えたので「メソッドでジェネリクスが使えない」わけではなく、 使えなかったのはメソッドが型パラメータを増やすことだった。
func Map[T, U any](s []T, f func(T) U) []U // OK: 関数
type Stack[T any] struct{ items []T } // OK: 型
func (s *Stack[T]) Push(v T) // OK: レシーバ由来の T は使える
func (s *Stack[T]) Map[U any](f func(T) U) *Stack[U]
// NG! syntax error: method must have no type parameters
1.27 ではこれが書ける。spec の Method declarations に載っている公式例:
type List[E any] []E
func (l List[E]) Apply[F any](f func(E) F) List[F] {
applied := make(List[F], 0, len(l))
for _, v := range l {
applied = append(applied, f(v))
}
return applied
}
効くのは 写像変換の形をしたメソッドである。List[E] の E はレシーバから来るが、
変換先の F はレシーバのどこにも書かれていない。だから 1.26 まではメソッドにできず、
パッケージレベル関数に追い出すしかなかった。Push(v T) のように
「E を消費するだけ」のメソッドは昔から書けている。
何が変わって、何が変わっていないか
型の表現力は増えていない。List[F] を返すこと自体は関数版の Apply でもできていた。
変わるのは置き場所で、置き場所が変わると読み方と見つかり方が変わる。
提案本文が挙げている利点もそこにある。
x.a().b().c() may naturally be read left to right, whereas c(b(a(x))) is evaluated inside out.
実装方式も既存のジェネリクスと同じで、新しい機構は入っていない (GC shape stenciling と dictionary)。変わったのは 「メソッドは何のためにあるのか」という見方のほうである (メソッドはレシーバを持つ関数)。
代償
インターフェースを満たせない。これは実装上の難しさが解決されなかった結果を そのまま受け入れたもので、Go FAQ が却下した4案 が "unacceptable from a design point of view" として却下した案そのものである。 詳細は ジェネリクスメソッドはインターフェースを満たさない。
同じ割り切りの裏返しとして、関数だと通りメソッドだと通らないシグネチャ の制限も残った。
現況 (2026-08-15 時点)
GOEXPERIMENT=genericmethodsは 2026-06-15 にフラグごと削除された。無条件で有効- 標準ライブラリで入ったジェネリクスメソッドは 標準ライブラリ唯一のジェネリクスメソッド rand.N の1件だけ
- 静的解析ツール側にはまだ影響が残っている (静的解析から見たジェネリクスメソッド / linter が Go 1.27 に追いついていない)