שיעורי מודול (3/5)
כללי (Go 1.18+)
מאז Go 1.18 (מרץ 2022), פרמטרי סוג זמינים: ניתן לפרמטר פונקציות וסוגים על פני סוגים. הם מאפשרים לך לכתוב Map, Filter, Set[T], LinkedList[T] ללא שכפול קוד וללא interface{} + הצהרות סוג זמן ריצה.
פונקציה כללית: התחביר
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 מאפשר שוויון אבל לא < או >.
func Index[T comparable](s []T, x T) int {
for i, v := range s {
if v == x { return i }
}
return -1
}עבור </> אתה צריך אילוץ מותאם אישית.
אילוץ מותאם אישית: סוג איגודים
אילוץ הוא ממשק עם סעיפי "אלמנט מסוג":
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מדויק.
אילוץ יכול גם לערבב שיטות ורכיבי סוג:
type Stringable interface {
~string
Len() int
}סוגים גנריים
לא רק פונקציות: למבנים וממשקים יכולים להיות גם פרמטרים מסוג.
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). - אתה מפרמטר "כי אתה יכול": מקרה שימוש יחיד ← צור גרסה קונקרטית שלו.
תרגילים
Definisci la funzione generica Min[T הורה](א, ב ט) T che ritorna il minore usando l'operatore <. Il constraint הוזמן è già fornito.
הפתרון זמין לאחר 3 ניסיונות
Implementa Map[T, U any](s []T, f func(T) U) []U: applica f a ogni elemento e restituisce il nuovo slice.
הפתרון זמין לאחר 3 ניסיונות
Quale constraint consente l'operatore מובנה == ma NON l'operatore <?
func Index[T ???](s []T, x T) int { ... }