الانتقال إلى المحتوى الرئيسي
الوحدة 5 · الدرس 5 من 525/50 في الدورة~10 min
دروس الوحدة (5/5)

نمط المنشئ `الجديد...`

لا يحتوي Go على كلمة رئيسية constructor. الاتفاقية هي ** مصنع دالة ** تُرجع قيمة أو مؤشرًا تمت تهيئته بشكل صحيح. بواسطة يُطلق عليه عادةً اسم NewT (أو NewXxx).

النمط الأساسي: NewT

Go
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):

Go
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...
}

هذا هو النمط الاصطلاحي لأي منشئ به الشروط المسبقة: اتصال قاعدة البيانات، مقبض الملف، تكوين الخادم، وما إلى ذلك.

منشئون متعددون

إذا كان لديك "طرق" متعددة للإنشاء، فاستخدم أسماء وصفية:

Go
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }

لا يوجد تحميل زائد في Go: الاسم واضح.

الخيارات الوظيفية (لمحة متقدمة)

عندما يكون هناك العديد من المعلمات الاختيارية، يكون النمط الاصطلاحي هو "الخيارات الوظيفية":

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 هو بالفعل كائن مزامنة جاهز للاستخدام. نفس الشيء بالنسبة لـ bytes.Buffer.

القاعدة هي: "اجعل القيمة صفر مفيدة". إذا كنت تستطيع، لا منشئ إلزامي.

جربه

تمرين#go.m5.l5.e1
المحاولات: 0جارٍ التحميل…

اكتب وظيفة المصنع NewUser(name string, age int) *User الذي يُرجع &User{Name: name, Age: age}.

جارٍ تحميل المحرر…
إظهار التلميح

استخدم الحرفي `&User{...}` لإرجاع المؤشر.

الحل متاح بعد 3 من المحاولات

تمرين#go.m5.l5.e2
المحاولات: 0جارٍ التحميل…

تحويل NewUser إلى (سلسلة اسم) (*مستخدم، خطأ): إذا كان الاسم == '' يُرجع لا شيء، أخطاء. جديد('nome obbligatorio').

جارٍ تحميل المحرر…
إظهار التلميح

إذا كانت هناك شروط مسبقة، قم بإرجاع (*T، خطأ) وإرجاع nil + خطأ عند الفشل.

الحل متاح بعد 3 من المحاولات

Quiz#go.m5.l5.e3
جاهز

ما هو الاصطلاح الاصطلاحي للمنشئين في Go؟

Go
// Which signature is more idiomatic?
خيارات الإجابة

خلاصة

  • لا constructor: استخدم وظيفة NewT (أو New داخل الحزمة التي تحمل نفس الاسم).
  • ارجع *T للحالة البسيطة؛ (*T, error) بشروط مسبقة أو التحقق من الصحة.
  • عند حدوث خطأ: قم بإرجاع nil كمؤشر والخطأ التوضيحي كقيمة ثانية.
  • لا التحميل الزائد. استخدم أسماء وصفية (NewUserFromJSON، NewAdmin).
  • "اجعل القيمة الصفرية مفيدة": إذا استطعت، فإن المنشئ غير ضروري.
  • نمط متقدم للعديد من المعلمات الاختيارية: الخيارات الوظيفية.