שיעורי מודול (5/5)
תבנית הקונסטרוקטור 'חדש...'
ל-Go אין מילת מפתח constructor. הכינוס הוא מפעל
פונקציה שמחזירה ערך או מצביע מאותחלים כהלכה. מאת
שם זה נקרא בדרך כלל NewT (או NewXxx).
תבנית בסיס: NewT
type User struct {
Name string
Age int
}
func NewUser(name string, age int) *User {
return &User{Name: name, Age: age}
}
u := NewUser("Ada", 36)
fmt.Println(u.Name)יתרונות על פני &User{...} המילולי הישיר:
- אתה מרכז אימות וברירות מחדל.
- אתה יכול לקבל שדות לא מיוצאים ולאכלס אותם רק מהקונסטרוקטור.
- אתה יכול לשנות את היישום מבלי לשבור את המתקשרים.
בנאי עם אימות: (*T, שגיאה)
כאשר האתחול עלול להיכשל, החזר את (*T, error):
import "errors"
func NewUser(name string, age int) (*User, error) {
if name == "" {
return nil, errors.New("nome obbligatorio")
}
if age < 0 {
return nil, errors.New("eta non valida")
}
return &User{Name: name, Age: age}, nil
}
u, err := NewUser("Ada", 36)
if err != nil {
// handle...
}זהו התבנית האידיומטית עבור כל בנאי עם תנאים מוקדמים: חיבור db, טיפול בקובץ, תצורת שרת וכו'.
מספר בנאים
אם יש לך מספר "דרכים" לבנות, השתמש בשמות תיאוריים:
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }אין עומס יתר ב-Go: השם אינו ברור.
אפשרויות פונקציונליות (הצצה מתקדמת)
כאשר ישנם פרמטרים אופציונליים רבים, הדפוס האידיומטי הוא "אפשרויות פונקציונליות":
type Option func(*Server)
func WithPort(p int) Option {
return func(s *Server) { s.Port = p }
}
func WithTLS(cert, key string) Option {
return func(s *Server) { s.Cert, s.Key = cert, key }
}
func NewServer(opts ...Option) *Server {
s := &Server{Port: 8080} // default
for _, opt := range opts {
opt(s)
}
return s
}
s := NewServer(WithPort(9000), WithTLS("c.pem", "k.pem"))זה יותר מילולי ממילה מילולית אבל קנה מידה טוב עם רבים אופציונליים
פרמטרים ושומר על תאימות לאחור (הוספת Option חדש
לא שובר מתקשרים קיימים).
כאשר אתה לא צריך קונסטרוקטור
אם ערך האפס של הסוג כבר שימושי, תן למתקשר להשתמש ב-
ישיר מילולי. דוגמה קנונית: ל-sync.Mutex אין בנאי,
var m sync.Mutex הוא כבר mutex מוכן לשימוש. אותו דבר עבור bytes.Buffer.
הכלל הוא: "הפוך את ערך האפס לשימושי". אם אתה יכול, לא בנאי חובה.
נסה את זה
כתוב את פונקציית היצרן NewUser(מחרוזת שם, גיל int) *משתמש שמחזיר &User{Name: name, Age: age}.
הצג רמז
השתמש ב'&User{...}' המילולי כדי להחזיר מצביע.
הפתרון זמין לאחר 3 ניסיונות
הפוך את NewUser ל(מחרוזת שם) (*User, error): if name == '' החזר אפס, errors.New('nome obbligatorio').
הצג רמז
אם יש תנאים מוקדמים, החזר (*T, שגיאה) והחזר אפס + שגיאה בכשל.
הפתרון זמין לאחר 3 ניסיונות
מהי המוסכמה האידיומטית עבור בנאים ב-Go?
// Which signature is more idiomatic?לְסַכֵּם
- לא
constructor: השתמש בפונקציהNewT(אוNewבתוך החבילה בעלת שם זהה). - החזר
*Tעבור המארז הפשוט;(*T, error)עם תנאים מוקדמים או אימות. - בשגיאה: החזר את
nilכמצביע ושגיאת ההסבר כערך השני. - אין עומס יתר; השתמש בשמות תיאוריים (
NewUserFromJSON,NewAdmin). - "הפוך את ערך האפס לשימושי": אם אתה יכול, הבנאי מיותר.
- דפוס מתקדם עבור פרמטרים אופציונליים רבים: אפשרויות פונקציונליות.