1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go1.24GenericsのType Aliasを利用する

Last updated at Posted at 2025-02-22

はじめに

Go 1.24のリリースに伴い、Generics type aliasが利用できるようになりました。
実際に触ってみたく、記事にしました!

スライスのジェネリック型エイリアス

package main

import "fmt"

// スライス型のエイリアス
type List[T any] = []T

func main() {
	// int型のList
	var intList List[int] = []int{1, 2, 3}
	fmt.Println(intList) // 出力: [1 2 3]

	// string型のList
	var stringList List[string] = []string{"A", "B", "C"}
	fmt.Println(stringList) // 出力: [A B C]
}

type List[T any] = []TはT はジェネリック型パラメータで、「任意の型(any)」を受け取ることを意味します。

実行結果
~/go/go_generics  $ go run main.go 
[1 2 3]
[A B C]
// Map型のエイリアス
type Dictionary[K comparable, V any] = map[K]V

func main() {
	// string → int のマップ
	var ageMap Dictionary[string, int] = map[string]int{
		"Alice": 30,
		"Bob":   25,
	}
	fmt.Println(ageMap) // 出力: map[Alice:30 Bob:25]

	// int → string のマップ
	var idMap Dictionary[int, string] = map[int]string{
		1: "Alice",
		2: "Bob",
	}
	fmt.Println(idMap) // 出力: map[1:Alice 2:Bob]
}

type Dictionary[K comparable, V any] = map[K]V
Kはマップのキーとなる型で、==や!=で比較できる型に限定されます。

~/go/go_generics  $ go run main.go
map[Alice:30 Bob:25]
map[1:Alice 2:Bob]
package main

import "fmt"

// ジェネリック構造体
type Container[T any] struct {
	Value T
}

// 型エイリアス
type Box[T any] = Container[T]

func main() {
	// BoxはContainerと同じ役割
	intBox := Box[int]{Value: 100}
	fmt.Println(intBox)  // 出力: {100}

	stringBox := Box[string]{Value: "Hello"}
	fmt.Println(stringBox)  // 出力: {Hello}
}
実行結果
~/go/go_generics  $ go run main.go
{100}
{Hello}

型に制約を持たせる

main.go
package main

import "fmt"

// 制約: 数値型のみ
type Number interface {
	int | float64
}

// 制約付きジェネリック構造体
type Container[T Number] struct {
	Value T
}

func main() {
	// int型は許可
	intBox := Container[int]{Value: 100}
	fmt.Println(intBox) // 出力: {100}

	// float64型も許可
	floatBox := Container[float64]{Value: 99.9}
	fmt.Println(floatBox) // 出力: {99.9}

	// string型はエラー
	stringBox := Container[string]{Value: "Hello"} // コンパイルエラー
}

→確かにエラーが起きていることを確認。
image.png

型の拡張

上記例の場合、Number型しか許容していませんでした。ただ、Stringも対応させたい場合は下記のように実施します。

main
package main

import "fmt"

// 数値型制約
type NumberInterface interface {
	int | float64
}

// 文字列型制約
type StringInterface interface {
	string
}

// NumberまたはStringを許可
type NumberOrString interface {
	NumberInterface | StringInterface
}

// 制約付きジェネリック構造体
type Container[T NumberOrString] struct {
	Value T
}

func main() {
	// 許可された型
	intBox := Container[int]{Value: 100}
	fmt.Println(intBox)  // 出力: {100}

	floatBox := Container[float64]{Value: 99.9}
	fmt.Println(floatBox)  // 出力: {99.9}

	stringBox := Container[string]{Value: "Hello"}
	fmt.Println(stringBox)  // 出力: {Hello}

	// 許可されない型(例: bool)
	// boolBox := Container[bool]{Value: true}  // コンパイルエラー
}

→確かにStringは許容し、他はエラーが起きていることを確認。
image.png

最後に

Genericsを使うことで今まで汎用化できなかった箇所も改善されそうですね!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?