إعادة أكثر من قيمة
اسرد أنواع النتائج بين قوسين. أعد القيم مفصولة بفواصل، واستقبلها بالطريقة نفسها.
الدالتان المدمجتان min وmax موجودتان منذ Go 1.21. يجب أن يستقبل المستدعي كل النتائج: تفشل x := minMax(nums) في الترجمة برسالة assignment mismatch: 1 variable but minMax returns 2 values.
اصطلاح (value, error)
أشيع سبب لإعادة قيمتين هو الإبلاغ عن الفشل. اصطلاحًا يأتي الخطأ أخيرًا، وعندما لا يكون nil يجب اعتبار النتائج الأخرى بلا معنى.
المخرجات:
port: 8080
error: port "http": strconv.Atoi: parsing "http": invalid syntax
error: port out of range
عند الفشل أعد القيمة الصفرية لكل نتيجة أخرى (0 و"" وnil). النمط الكامل، بما في ذلك التغليف والفحص، في صفحة معالجة الأخطاء.
نمط comma-ok
تعيد عدة عمليات مدمجة قيمة ثانية اختيارية من النوع bool تقول هل القيمة الأولى حقيقية. يُسمّى المتغيّر اصطلاحًا ok.
هذه الأشكال الثلاثة (البحث في خريطة، وتأكيد النوع، والاستقبال من قناة) خاصة: تعيد قيمة واحدة أو قيمتين حسب عدد المتغيّرات التي تسند إليها. دوالك الخاصة لا تستطيع ذلك. الدالة المعرّفة بنتيجتين تعيد دائمًا نتيجتين.
المعرّف الفارغ
يستقبل _ قيمة ويرميها. استخدمه للنتائج التي لا تحتاجها:
_, err := fmt.Sscan(input, &n)
key, _ := parseLine(line)
تجاهل خطأ بـ _ يُترجم، فافعل ذلك فقط عندما تعرف أن الاستدعاء لا يفشل أو أن الفشل لا يهمّ. تعيد strings.Builder.WriteString مثلًا خطأ nil دائمًا؛ أما إغلاق ملف بعد الكتابة فيه فلا.
النتائج المسمّاة
يمكن أن تكون لمعاملات النتائج أسماء. تُعرَّف في بداية الدالة، وتُهيّأ بقيمها الصفرية، وتعيد return دون قيم ما تحمله.
تظهر الأسماء في مخرجات go doc، وهذا يفيد عندما تتشارك نتيجتان نوعًا: (quotient, remainder int) تقول أكثر من (int, int).
return المجرّدة في دالة طويلة صعبة القراءة، لأن على القارئ الرجوع ليرى ما تحمله النتائج. النصيحة المعتادة: سمِّ النتائج عندما توثّق الأسماء شيئًا، واكتب مع ذلك return quotient, remainder صراحة ما لم تكن الدالة بضعة أسطر.
النتائج المسمّاة وdefer
تُنفَّذ الدالة المؤجّلة بعد أن تضبط عبارة return النتائج وقبل أن يتلقّاها المستدعي. مع النتائج المسمّاة تستطيع الدالة المؤجّلة قراءتها وتغييرها. بهذا تضيف سياقًا إلى أي خطأ تعيده دالة، أو تحوّل panic إلى خطأ.
يطبع هذا load : empty name ثم <nil>. تسند return errors.New(...) أولًا إلى err، ثم تغلّفه الدالة المؤجّلة. المزيد في صفحة defer.
تظليل نتيجة مسمّاة
تعيش النتائج المسمّاة في النطاق الأعلى للدالة. عبارة := داخل كتلة متداخلة تنشئ متغيّرًا جديدًا بالاسم نفسه، ثم تعيد return المجرّدة المتغيّر الخارجي.
func find() (n int, err error) {
if true {
n, err := compute() // new n and err, shadowing the results
_ = n
_ = err
}
return // returns 0, nil
}
يكتشف المترجم أسوأ حالة: return مجرّدة داخل الكتلة التي تُظلَّل فيها نتيجة تفشل برسالة result parameter err not in scope at return. لكنه لا يكتشف النسخة السابقة، حيث تقع العودة خارج الكتلة. استخدم = بدل := عندما تقصد متغيّرات النتائج.
أخطاء شائعة
- استخدام القيمة عندما لا يكون err مساويًا لـ nil. افحص
errأولًا. للدالة الحرية في إعادة قيمة لا معنى لها مع الخطأ. - إعادة مؤشر nil ذي نوع كخطأ. تعيد
var e *MyErr; return eقيمةerrorليست nil. أعدnilحرفيًا عند النجاح. - نتائج كثيرة جدًا. ثلاث نتائج أو أكثر بمعانٍ مختلطة صعبة الاستخدام. أعد بنية بدلًا من ذلك.
الأسئلة الشائعة
كيف تعيد عدة قيم من دالة في Go؟
اسرد أنواع النتائج بين قوسين وأعد القيم مفصولة بفواصل: func minMax(xs []int) (int, int) { ...; return lo, hi }. يسندها المستدعي كلها دفعة واحدة: lo, hi := minMax(nums).
كيف أتجاهل إحدى القيم المعادة في Go؟
أسندها إلى المعرّف الفارغ _: _, err := strconv.Atoi(s) أو n, _ := strconv.Atoi(s). لا يمكنك حذف قيمة بالكامل: يجب أن يطابق عدد المتغيّرات في الطرف الأول من الإسناد عدد النتائج.
ما هي القيم المعادة المسمّاة في Go؟
معاملات نتائج لها أسماء، مثل func split(n int) (half, rest int). تبدأ بقيمها الصفرية، ويمكن الإسناد إليها في الجسم، وتعيد return المجرّدة قيمها الحالية. وتتيح أيضًا لدالة مؤجّلة تغيير ما يتلقّاه المستدعي.
هل أستخدم العودة المجرّدة (naked return) في Go؟
في الدوال القصيرة فقط. return المجرّدة في دالة طويلة تخفي ما يُعاد وتسهّل أخطاء التظليل. توصي أدلة أسلوب Go بتسمية النتائج للتوثيق وإعادة قيم صريحة في أي دالة أطول من بضعة أسطر.