«أين معلماتي الاختيارية؟» — صرخة روح مطور Go
لقد انتقلت للتو إلى Go من Python أو JavaScript وتكتب دالة لإرسال بريد إلكتروني. في Python، كان الأمر يبدو كالتالي:
def send_email(to, subject, cc=None, bcc=None, attachments=None): passالأمر بسيط: cc و bcc و attachments هي معلمات اختيارية. يمكنك عدم تمريرها، وستعمل الدالة بقيم افتراضية.
ولكن ها هي المشكلة: في Go لا يوجد تحميل زائد للدوال ولا وسائط مسماة بقيم افتراضية. يؤكد مجتمع Stack Overflow: سؤال «Optional Parameters in Go?» يحصل على آلاف المشاهدات. هذا ألم حقيقي للمبتدئين.
الخبر السار: هناك على الأقل 5 طرق أنيقة في Go لحل هذه المشكلة. في هذه المقالة، سنستعرضها جميعًا — من البسيطة إلى الاحترافية.
لماذا Go «صارمة» إلى هذا الحد؟
تخلت فريق Go عن المعلمات الاختيارية عن قصد من أجل:
- تبسيط قراءة الكود — ترى دائمًا عدد الوسائط التي يتم تمريرها إلى الدالة.
- تجنب السلوك السحري — لا قيم افتراضية غير متوقعة.
- تسريع التجميع — سكر نحوي أقل.
لكن هذا لا يعني أنه لا يمكنك جعل الكود مرنًا. دعنا نرى كيفية تجاوز القيود.
الطريقة 1: الدوال المتغيرة (Variadic Functions) — «رخيصة وفعالة»
أبسط طريقة هي استخدام علامة القطع ... لتمرير عدد متغير من الوسائط من نفس النوع.
package main
import "fmt"
// Sum تقبل أي عدد من الأعداد الصحيحةfunc Sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total}
func main() { fmt.Println(Sum(1, 2, 3)) // 6 fmt.Println(Sum(10, 20)) // 30 fmt.Println(Sum()) // 0 — تعمل أيضًا}الإيجابيات: البساطة، دعم مدمج في اللغة.
السلبيات: يجب أن تكون جميع الوسائط من نفس النوع. لا يمكنك قول «مرر سلسلة نصية، ثم عددًا صحيحًا اختياريًا».
الدوال المتغيرة في Go مناسبة تمامًا لمسجلات الأحداث، والجامعين، وأي عمليات يكون فيها عدد البيانات غير معروف مسبقًا.
الطريقة 2: هيكل التكوين (Configuration Struct) — «عندما تكون المعلمات كثيرة»
إذا كان لديك أكثر من 2-3 معلمات اختيارية من أنواع مختلفة — استخدم هيكلًا.
package main
import "fmt"
type EmailConfig struct { CC []string BCC []string Attachments []string IsHTML bool}
func SendEmail(to, subject, body string, cfg EmailConfig) { fmt.Printf("To: %s, Subject: %s", to, subject) if cfg.IsHTML { fmt.Println("HTML mode enabled") } if len(cfg.CC) > 0 { fmt.Printf("CC: %v", cfg.CC) }}
func main() { // استخدام القيم الافتراضية (القيم الصفرية) SendEmail("user@example.com", "Hello", "Body", EmailConfig{})
// تجاوز بعض الحقول cfg := EmailConfig{ CC: []string{"boss@example.com"}, IsHTML: true, } SendEmail("user@example.com", "Hello", "Body", cfg)}لاحظ: القيم الصفرية في Go (سلسلة فارغة، 0، nil للشرائح) تصبح القيم الافتراضية. هذا هو تنفيذ المعلمات الاختيارية في Go من خلال الهياكل.
الإيجابيات: قابل للقراءة، محدد النوع، سهل التوسيع.
السلبيات: تحتاج إلى إنشاء هيكل في كل مرة، حتى لو لم تغير شيئًا.
الطريقة 3: نمط الخيارات الوظيفية (Functional Options Pattern) — «المعيار الذهبي لـ Go»
هذا النمط ابتكره ديف تشيني، أحد المطورين الرئيسيين لـ Go. يُستخدم في مكتبات مثل gRPC و AWS SDK والمكتبة القياسية الخاصة بـ Go (على سبيل المثال،
المدونات
توصيات الكتب
اقرأ أيضًا