🤖

Go チルダ(~)[Generics]

2022/03/20に公開

Go Gereticsのチルダ(~)

version 1.18よりGenericsが利用可能に。

Go 1.18 Release Notes - The Go Programming Languageリリースノートのサンプルより以下のコードのなかで気になった箇所が。

func Print[T ~int|~string](t T) {
	fmt.Printf("%d", t)
}

T型パラメータの型の前についている、~ は何...?

それを探るべく我々はGo Specへ向かった。

Underlying Type

Interface typesの説明に、以下のような構文木の定義がある。

InterfaceType  = "interface" "{" { InterfaceElem ";" } "}" .
InterfaceElem  = MethodElem | TypeElem .
MethodElem     = MethodName Signature .
MethodName     = identifier .
TypeElem       = TypeTerm { "|" TypeTerm } .
TypeTerm       = Type | UnderlyingType .
UnderlyingType = "~" Type .

一番下の行~は、Underlying Type というものらしい。

Underlying Typeに関しては、この説明が一番わかりやすかった。

入門Go言語仕様 Underlying Type / Go Language Underlying Type - Speaker Deck

Underlying Typeはその型の基礎となる型のことで、最初の~intの例は、基礎となる型がintである型を要求する、ということ。

つまり、こういうことができる。

package main

import "fmt"

type MyInt int
type MyString string
type MyExtendedString MyString

func Print[T ~int | ~string](t T) {
	fmt.Printf("%d", t)
}

func main() {

	Print(MyInt(1))
	Print(MyString("foo"))
	Print(MyExtendedString("bar"))
}

Underlying Typeが一致する独自型を渡すことができるということ。

その他の参考

型仕様周りは奥が深いので、少し掘り下げることにする。

Discussion