דילוג לתוכן המרכזי
מודול 10 · שיעור 3 מתוך 548/50 בקורס~15 min
שיעורי מודול (3/5)

כללי (Go 1.18+)

מאז Go 1.18 (מרץ 2022), פרמטרי סוג זמינים: ניתן לפרמטר פונקציות וסוגים על פני סוגים. הם מאפשרים לך לכתוב Map, Filter, Set[T], LinkedList[T] ללא שכפול קוד וללא interface{} + הצהרות סוג זמן ריצה.

פונקציה כללית: התחביר

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}

שלושה אלמנטים חדשים:

  • [T, U any] אחרי השם: מצהיר על פרמטרי הסוג עם האילוצים שלהם.
  • any = אילוץ שמקבל כל סוג (כינוי של interface{} מאז Go 1.18).
  • הסקת מסקנות: קורא Map([]int{...}, ...) אתה לא צריך לכתוב Map[int, int](...): המהדר מסיק T=int, U=int.

לפעמים ההסקה אינה מספיקה (למשל, בנאים ללא ארגומנטים T) ויש צורך במופע מפורש: New[*Server]().

אילוצים מובנים

אילוץהמשמעות
anyכל סוג (== interface{}).
comparableסוגים עם == ו-!=: מספרי, מחרוזת, bool, מצביעים, ערוצים, מערכים/מבנים דומים.

comparable מאפשר שוויון אבל לא < או >.

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

עבור </> אתה צריך אילוץ מותאם אישית.

אילוץ מותאם אישית: סוג איגודים

אילוץ הוא ממשק עם סעיפי "אלמנט מסוג":

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

func Min[T Ordered](a, b T) T {
    if a < b { return a }
    return b
}
  • | = איחוד: מקבל כל אחד מהסוגים הרשומים.
  • ~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{} + קביעות סוג (איבוד בטיחות סוג).

לא כאשר:

  • מספיק ממשק עם שיטה אחת או שתיים וקריא יותר (io.Reader, fmt.Stringer).
  • אתה מפרמטר "כי אתה יכול": מקרה שימוש יחיד ← צור גרסה קונקרטית שלו.

תרגילים

פעילות גופנית#go.m10.l3.e1
ניסיונות: 0טוען...

Definisci la funzione generica Min[T הורה](א, ב ט) T che ritorna il minore usando l'operatore <. Il constraint הוזמן è già fornito.

טוען עורך...

הפתרון זמין לאחר 3 ניסיונות

פעילות גופנית#go.m10.l3.e2
ניסיונות: 0טוען...

Implementa Map[T, U any](s []T, f func(T) U) []U: applica f a ogni elemento e restituisce il nuovo slice.

טוען עורך...

הפתרון זמין לאחר 3 ניסיונות

Quiz#go.m10.l3.e3
מוכן

Quale constraint consente l'operatore מובנה == ma NON l'operatore <?

Go
func Index[T ???](s []T, x T) int { ... }
אפשרויות תשובה