المسارات
/
Go
Go
/
التمارين
/
غرفة الفرز
غرفة الفرز

غرفة الفرز

تمرين تعلّمي

مقدمة

تحويل الأنواع

يتطلب Go تحويلًا صريحًا بين الأنواع المختلفة. يتم التحويل بين الأنواع (المعروف أيضًا بـ type casting) عبر دالة تحمل اسم النوع المراد التحويل إليه. على سبيل المثال، لتحويل int إلى float64 عليك القيام بما يلي:

var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)

التحويل بين الأنواع الأولية والسلاسل النصية

توجد حزمة strconv للتحويل بين الأنواع الأولية (مثل int) وstring.

import "strconv"

var intString string = "42"
var i, err = strconv.Atoi(intString)

var number int = 12
var s string = strconv.Itoa(number)

تأكيدات النوع

قد تُدخل الواجهات في Go غموضًا بشأن النوع الكامن. يتيح لنا تأكيد النوع استخراج القيمة الملموسة الكامنة لقيمة الواجهة باستخدام هذه الصيغة: interfaceVariable.(concreteType).

على سبيل المثال:

var input any = 12
number := input.(int)

ملاحظة: سيؤدي هذا إلى panic إذا لم يحتوِ متغير الواجهة على قيمة من النوع الملموس.

يمكننا اختبار ما إذا كانت قيمة الواجهة تحمل نوعًا ملموسًا محددًا بالاستفادة من قيمتي الإرجاع لتأكيد النوع: القيمة الكامنة وقيمة منطقية تخبرنا ما إذا نجح التأكيد. على سبيل المثال:

str, ok := input.(string) // no panic if input is not a string

إذا كانت input تحمل string، فستكون str هي القيمة الكامنة وستكون ok هي صحيح. وإذا لم تكن input تحمل string، فستكون str هي القيمة الصفرية للنوع string (أي ""، السلسلة النصية الفارغة) وستكون ok هي خطأ. ولا يحدث panic في أي حالة.

تبديل النوع

يمكن لـتبديل النوع إجراء عدة تأكيدات نوع بالتتابع. وهو يستخدم الصيغة نفسها التي يستخدمها تأكيد النوع (interfaceVariable.(concreteType))، لكن يُستبدل concreteType بالكلمة المفتاحية type. إليك مثالًا:

var i any = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}

switch v := i.(type) {
case int:
    fmt.Printf("the integer %d\n", v)
case string:
    fmt.Printf("the string %s\n", v)
default:
    fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}

التعليمات

تعمل جين في غرفة الفرز في مصنع كبير. تحتاج غرفة الفرز إلى معالجة كل ما يصل إليها بتصنيفه ووضع ملصق عليه. جين مسؤولة عن الأشياء التي صُنّفت مسبقًا كأعداد، وتحتاج إلى برنامج يساعدها في الفرز.

معظم القيم الأولية ينبغي أن تحصل على ملصقات مباشرة. بالنسبة إلى الأعداد، تريد سلاسل نصية تقول "This is the number 2.0" (إذا كان العدد 2). تريد جين المخرَج نفسه للأعداد الصحيحة والأعداد العشرية.

هناك بعض الواجهات Box التي يجب فكّها للحصول على محتوياتها. بالنسبة إلى NumberBox، تريد سلاسل نصية تقول "This is a box containing the number 3.0" (إذا أرجعت الطريقة Number() القيمة 3). وبالنسبة إلى FancyNumberBox، تريد سلاسل نصية تقول "This is a fancy box containing the number 4.0"، ولكن فقط إذا كان النوع FancyNumber.

أي شيء غير متوقع ينبغي أن يقول "Return to sender" حتى تتمكن جين من إعادته إلى مصدره.

1. وصف الأعداد البسيطة

تريد جين أن تُرجع الأعداد سلاسل نصية مثل "This is the number 2.0" (مع رقم واحد بعد الفاصلة العشرية):

fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3

2. وصف صندوق الأعداد

تريد جين أن تُرجع صناديق الأعداد سلاسل نصية مثل "This is a box containing the number 2.0" (مرة أخرى، مع رقم واحد بعد الفاصلة العشرية):

fmt.Println(DescribeNumberBox(numberBoxContaining{12}))
// Output: This is a box containing the number 12.0

3. تنفيذ طريقة تستخرج العدد من صندوق أعداد مميّز

تحتاج جين إلى دالة مساعدة لاستخراج العدد من FancyNumberBox. إذا كان FancyNumberBox من نوع FancyNumber، فاستخرج قيمته وحوّلها من string إلى int. أي نوع آخر من FancyNumberBox ينبغي أن يُرجع 0.

fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0

4. وصف صندوق الأعداد المميّز

إذا كان FancyNumberBox من نوع FancyNumber، تريد جين سلاسل نصية تقول "This is a fancy box containing the number 4.0". أي نوع آخر من FancyNumberBox ينبغي أن يقول "This is a fancy box containing the number 0.0".

fmt.Println(DescribeFancyNumberBox(FancyNumber{"10"}))
// Output: This is a fancy box containing the number 10.0
fmt.Println(DescribeFancyNumberBox(AnotherFancyNumber{"4"}))
// Output: This is a fancy box containing the number 0.0

ملاحظة: ينبغي أن نستخدم الدالة ExtractFancyNumber!

5. تنفيذ DescribeAnything التي تستخدمها جميعًا

هذه هي الدالة الرئيسية التي تحتاجها جين، وهي تأخذ أي مدخل. ينبغي أن تُفوّض DescribeAnything إلى الدوال الأخرى بناءً على نوع القيمة المُمرَّرة. وبشكل أكثر تحديدًا:

  • ينبغي أن تُفوّض كلٌّ من int وfloat64 إلى DescribeNumber
  • ينبغي أن تُفوّض NumberBox إلى DescribeNumberBox
  • ينبغي أن تُفوّض FancyNumberBox إلى DescribeFancyNumberBox
  • أي شيء آخر ينبغي أن تكون نتيجته "Return to sender"
fmt.Println(DescribeAnything(numberBoxContaining{12.345}))
// Output: This is a box containing the number 12.3
fmt.Println(DescribeAnything("some string"))
// Output: Return to sender
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Go Exercism

مستعد لبدء غرفة الفرز؟

سجّل في Exercism لتتعلّم وتتقن Go عبر 34 مفهومًا166 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.