メインコンテンツにスキップ
モジュール 10 · レッスン 3 / 5コース内の 48/50~15 min
モジュールのレッスン (3/5)

ジェネリック (Go 1.18+)

Go 1.18 (2022 年 3 月) 以降、型パラメーター が利用可能になりました。関数と型は型に対してパラメーター化できます。これらを使用すると、コードを複製したり、​​PROTECTED_INLINE_4 + ランタイム型アサーションを使用したりせずに、Map、Filter、Set[T]、LinkedList[T] を作成できます。

汎用関数: 構文

Go
func Map[T, U any](s []T, f func(T) U) []U {
    out := make([]U, len(s))
    for i, v := range s {
        out[i] = f(v)
    }
    return out
}

doubled := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })
// doubled is []int{2, 4, 6}

3 つの新しい要素:

  • 名前の後の [T, U any]: 型パラメータとその制約を宣言します。
  • any = 任意の型を受け入れる制約 (Go 1.18 以降の interface{} のエイリアス)。
  • 推論: Map([]int{...}, ...) を呼び出す場合、Map[int, int](...) を記述する必要はありません。コンパイラは T=int, U=int を推論します。

場合によっては、推論だけでは十分ではなく (T 引数のないコンストラクターなど)、明示的なインスタンス化が必要になります: New[*Server]()。

組み込みの制約

制約意味
any任意のタイプ (== interface{})。
comparable== および != の型: 数値、文字列、ブール値、ポインター、チャネル、同等の配列/構造体。

comparable は等価性を許可しますが、< または > は許可しません。

Go
func Index[T comparable](s []T, x T) int {
    for i, v := range s {
        if v == x { return i }
    }
    return -1
}

</> の場合は、カスタム制約が必要です。

カスタム制約: 型共用体

制約は、「type element」句を含む インターフェイス です。

Go
type Ordered interface {
    ~int | ~int64 | ~float64 | ~string
}

func Min[T Ordered](a, b T) T {
    if a < b { return a }
    return b
}
  • | = Union: リストされているタイプのいずれかを受け入れます。
  • ~int = "int または type X int として定義された任意の型" (基になる型は同じ)。 ~ を使用しない場合は、正確な int のみとなります。

制約では メソッドと型要素を混在させることもできます。

Go
type Stringable interface {
    ~string
    Len() int
}

ジェネリックタイプ

関数だけでなく、構造体やインターフェイスも型パラメータを持つことができます。

Go
type Set[T comparable] struct {
    m map[T]struct{}
}

func NewSet[T comparable]() *Set[T] {
    return &Set[T]{m: make(map[T]struct{})}
}

func (s *Set[T]) Add(v T) { s.m[v] = struct{}{} }
func (s *Set[T]) Has(v T) bool { _, ok := s.m[v]; return ok }

s := NewSet[string]()
s.Add("ada")

メソッドは、型のパラメーターを超える型パラメーターを追加できません: func (s *Set[T]) MapTo[U any](...) コンパイルしません (意図的な設計上の制限)。

ジェネリック医薬品を使用する場合

はい:

  • ロジックは、いくつかのタイプ (コレクション、アルゴリズム、Map/Filter/Reduce などのヘルパー) で真に 同一 です。
  • 代わりの方法は、コードを複製するか、interface{} + 型アサーションを使用することです (型安全性が失われます)。

いいえ 次の場合:

  • 1 つまたは 2 つのメソッドを備えたインターフェイスで十分であり、より読みやすくなっています (io.Reader、fmt.Stringer)。
  • 「できるから」パラメータ化しています: 単一のユースケース → その具体的なバージョンを作成します。

演習

運動#go.m10.l3.e1
試行回数: 0読み込み中…

一般的な機能の定義 Min[T Ordered](a, b T) の操作方法 &lt;。 Il 制約は、fornito に命じられました。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

運動#go.m10.l3.e2
試行回数: 0読み込み中…

Map[T, U any](s []T, f func(T) U) []U を実装します。新しい要素を復元します。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

Quiz#go.m10.l3.e3
準備完了

Quale 制約組み込みの同意 l'operatore == ma NON l'operatore <?

Go
func Index[T ???](s []T, x T) int { ... }
回答の選択肢