フューチャー技術ブログ

Go 1.19 Genericsのアップデート

はじめに

こんにちは。DXユニットの村上です。
本記事はGo 1.19リリース連載の5本目です。関数やレシーバのジェネリクスの微修正についてご紹介します。

Release Noteでは次の箇所になります。

https://tip.golang.org/ref/spec#Declarations_and_scope

The scope of an identifier denoting a type parameter of a function or declared by a method receiver begins after the name of the function and ends at the end of the function body.

翻訳すると以下のようになります。

関数の型パラメータやメソッドレシーバで宣言されたもののスコープは、関数名の後ろから関数本体の終端までです。

しかし本アップデートはGo 1.19でリリース予定でしたが、Go 1.20でのリリースに変更されたようです。
https://github.com/golang/go/issues/51503#issuecomment-1154209161

よってGo 1.20リリース予定の紹介という感じになります。

従来の問題点

こちらのissueで問題提起されています。
https://github.com/golang/go/issues/51503

以下のコードが例として提示されています。

type T[T any] struct {} // OK

func (T[T]) Bar() {} // error: T is not a generic type

前者がOKなら後者もOKであるべきと議論されていました。

原因

後者がビルドエラーとなる原因は以下のissueで説明されています。
https://github.com/golang/go/issues/52038

func (T[T]) Bar() {}

[T]Tが外側(左側)のTを参照しているため、エラーとなるようです。

逆に外側をT以外にすればエラーにはなりません。

type Hoge[T any] struct{} // OK

func (Hoge[T]) Bar() {} // OK

後者のHoge[T]は前者のHoge[T any]をそれぞれ参照できているため問題ありません。

もしくは[T]を別の文字に置き換えても大丈夫です。

type T[T any] struct{} // OK

func (T[Hoge]) Bar() {} // OK

解決策

冒頭で引用したリリースノートの内容にすることで、これがエラーにならなくなります。
レシーバの中で宣言された型のスコープを関数名以降にします。
これによって、外側のTのスコープは関数名以降となり、[T]に適用されなくなります。

おわりに

かなりマイナーアップデートですが、Golangがより洗練された言語になることは間違いないかと思います。
修正範囲が大きいということで惜しくもGo 1.19でのリリースは見送られることになりましたが、Go 1.20では修正されるということで期待したいと思います。