أنماط المُنشئات
بناء مُنشئات Go وفق الأساليب الاصطلاحية
أنماط المُنشئات درس مجاني في Go Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Go Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Go Academy 4 دروس في المجموع.
لماذا نستخدم المُنشئات؟
لا تحتوي Go على كلمة مفتاحية new للأنواع، ولا على مُنشئات للفئات. والاصطلاح المتبع هو استخدام دالة باسم New... تتحقق من المدخلات وتعيد قيمة أو مؤشرًا مُهيّأً.
دالة New بسيطة
أعد مؤشرًا لضمان عمل المستدعي مع مثيل مشترك:
package main
import "fmt"
type Server struct {
Host string
Port int
}
func NewServer(host string, port int) *Server {
return &Server{Host: host, Port: port}
}
func main() {
s := NewServer("localhost", 8080)
fmt.Println(s.Host, s.Port)
}التحقق في المُنشئات
تُعد المُنشئات مكانًا مناسبًا للتحقق من المدخلات وإعادة خطأ:
package main
import ("errors"; "fmt")
type Config struct{ Workers int }
func NewConfig(workers int) (*Config, error) {
if workers < 1 {
return nil, errors.New("workers must be >= 1")
}
return &Config{Workers: workers}, nil
}
func main() {
c, err := NewConfig(4)
fmt.Println(c, err)
}نمط الخيارات الوظيفية
يتيح نمط الخيارات الوظيفية إعدادًا اختياريًا من دون كسر واجهة برمجة التطبيقات:
package main
import "fmt"
type Server struct{ host string; port int; timeout int }
type Option func(*Server)
func WithPort(p int) Option { return func(s *Server) { s.port = p } }
func WithTimeout(t int) Option { return func(s *Server) { s.timeout = t } }
func NewServer(host string, opts ...Option) *Server {
s := &Server{host: host, port: 8080, timeout: 30}
for _, o := range opts { o(s) }
return s
}
func main() {
s := NewServer("localhost", WithPort(9090), WithTimeout(60))
fmt.Println(s.port, s.timeout)
}نمط المُنشئ
بالنسبة إلى الكائنات المعقدة، يربط نمط المُنشئ طرق الإعداد ويعيد النتيجة:
package main
import "fmt"
type QueryBuilder struct{ table, where string; limit int }
func (q *QueryBuilder) Table(t string) *QueryBuilder { q.table = t; return q }
func (q *QueryBuilder) Where(w string) *QueryBuilder { q.where = w; return q }
func (q *QueryBuilder) Limit(n int) *QueryBuilder { q.limit = n; return q }
func (q *QueryBuilder) Build() string {
return fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT %d", q.table, q.where, q.limit)
}
func main() {
sql := (&QueryBuilder{}).Table("users").Where("age>18").Limit(10).Build()
fmt.Println(sql)
}إعادة قيمة أم مؤشر
أعد قيمة عندما تكون البنية صغيرة وغير قابلة للتغيير، وأعد مؤشرًا عندما تكون البنية كبيرة أو قابلة للتغيير أو تنفّذ واجهات:
- بنى الإعدادات الصغيرة ← قيمة
- الكائنات التي تحتفظ بحالة (خادم، عميل، مجموعة) ← مؤشر
- عند تنفيذ واجهة باستخدام مستقبِلات بمؤشر ← مؤشر
نمط القيم الافتراضية
استخدم دالة للقيم الافتراضية أو قالب بنية لتعيين قيم افتراضية مناسبة قبل تطبيق الخيارات:
package main
import "fmt"
type Cache struct{ maxSize int; ttlSecs int }
func defaultCache() Cache { return Cache{maxSize: 100, ttlSecs: 300} }
func NewCache(opts ...func(*Cache)) *Cache {
c := defaultCache()
for _, o := range opts { o(&c) }
return &c
}
func main() {
c := NewCache(func(c *Cache) { c.maxSize = 500 })
fmt.Println(c.maxSize, c.ttlSecs) // 500 300
}نمط Singleton
استخدم sync.Once لتهيئة مورد مشترك مرة واحدة بالضبط:
package main
import ("fmt"; "sync")
type DB struct{ DSN string }
var (
instance *DB
once sync.Once
)
func GetDB(dsn string) *DB {
once.Do(func() { instance = &DB{DSN: dsn} })
return instance
}
func main() {
db1 := GetDB("postgres://...")
db2 := GetDB("ignored")
fmt.Println(db1 == db2) // true
}اختبار المُنشئات
من السهل اختبار المُنشئات التي تعيد أخطاء:
package main
import ("errors"; "fmt")
type Pool struct{ size int }
func NewPool(size int) (*Pool, error) {
if size <= 0 { return nil, errors.New("size must be positive") }
return &Pool{size: size}, nil
}
func main() {
_, err := NewPool(-1)
fmt.Println(err) // size must be positive
p, _ := NewPool(5)
fmt.Println(p.size) // 5
}تجنب init()
تعمل دوال init() تلقائيًا، ويصعب اختبارها. لذا فضّل المُنشئات الصريحة التي تعيد أخطاء على التهيئة الضمنية داخل init().
تحقق سريع
ما الذي يحققه نمط الخيارات الوظيفية؟
مراجعة: أنماط المُنشئات
أهم النقاط:
- استخدم دوال
New...بوصفها مُنشئات - أعد أخطاء عند فشل التحقق
- استخدم الخيارات الوظيفية لإعداد اختياري مرن
- استخدم نمط المُنشئ لكائنات الاستعلام أو الإعداد المعقدة
- فضّل المُنشئات الصريحة على
init()
مهمة تدريبية
نفّذ مُنشئ NewHTTPClient باستخدام الخيارات الوظيفية. وادعم خيَارات WithTimeout وWithBaseURL وWithMaxRetries.
الأسئلة الشائعة
هل درس «أنماط المُنشئات» مجاني؟
نعم — نص درس «أنماط المُنشئات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Go Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Go Academy 4 دروس في المجموع.
ماذا ستتعلم في «أنماط المُنشئات»؟
بناء مُنشئات Go وفق الأساليب الاصطلاحية تتمرن على Go Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Go Academy؟
لا تُشترط خبرة سابقة. Go Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «أنماط المُنشئات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Go Academy هذا؟
نعم. كل درس في Go Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.