المسارات
/
Go
Go
/
التمارين
/
علم الأرصاد الجوية
علم الأرصاد الجوية

علم الأرصاد الجوية

تمرين تعلّمي

مقدمة

Stringer واجهة لتحديد الصيغة النصية للقيم.

تتكوّن الواجهة من طريقة String وحيدة:

type Stringer interface {
    String() string
}

يجب أن تمتلك الأنواع التي تريد تنفيذ هذه الواجهة طريقة String() تُرجع تمثيلًا نصيًا مقروءًا للبشر. ستبحث حزمة fmt (وكثير من الحزم الأخرى) عن هذه الطريقة لتنسيق القيم وطباعتها.

مثال: المسافات

لنفترض أننا نعمل على تطبيق يتعامل مع مسافات جغرافية مقيسة بوحدات مختلفة. عرفنا النوعين DistanceUnit وDistance كما يلي:

type DistanceUnit int

const (
	Kilometer    DistanceUnit = 0
	Mile         DistanceUnit = 1
)

type Distance struct {
	number float64
	unit   DistanceUnit
}

في المثال أعلاه، Kilometer وMile ثابتان من النوع DistanceUnit.

لا تنفّذ هذه الأنواع الواجهة Stringer لأنها تفتقر إلى الطريقة String. لذلك ستطبع دوال fmt قيم Distance باستخدام «الصيغة الافتراضية» في Go:

mileUnit := Mile
fmt.Sprint(mileUnit)
// => 1
// The result is '1' because that is the underlying value of the 'Mile' constant (see constant declarations above)

dist := Distance{number: 790.7, unit: Kilometer}
fmt.Sprint(dist)
// => {790.7 0}
// not a very useful output!

لكي يصبح المُخرَج أكثر إفادة، ننفّذ الواجهة Stringer للنوعين DistanceUnit وDistance بإضافة طريقة String إلى كل نوع:

func (sc DistanceUnit) String() string {
	units := []string{"km", "mi"}
	return units[sc]
}

func (d Distance) String() string {
	return fmt.Sprintf("%v %v", d.number, d.unit)
}

ستستدعي دوال حزمة fmt هذه الطُرق عند تنسيق قيم Distance:

kmUnit := Kilometer
kmUnit.String()
// => km

mileUnit := Mile
mileUnit.String()
// => mi

dist := Distance{
	number: 790.7,
	unit: Kilometer,
}
dist.String()
// => 790.7 km

التعليمات

يعمل فريقك على تطبيق للأرصاد الجوية. وقد عرّفوا API يضم أنواعًا وثوابت متنوعة تمثل بيانات الأرصاد الجوية، انظر الملف meteorology.go.

مهمتك هي إضافة طرق String مناسبة إلى جميع الأنواع بحيث تُنفّذ الواجهة Stringer.

1. نفّذ الواجهة Stringer للنوع TemperatureUnit

بعد بعض النقاش، اتفق الفريق على أن وحدة الحرارة ستكون إما Celsius أو Fahrenheit. ينبغي تنسيق القيم كما هو موضح في الأمثلة أدناه.

اجعل النوع TemperatureUnit يُنفّذ الواجهة Stringer بإضافة طريقة String إليه. يجب أن تُرجع هذه الطريقة السلسلة النصية "°C" إذا كانت وحدة الحرارة Celsius أو "°F" إذا كانت وحدة الحرارة Fahrenheit.

celsiusUnit := Celsius
fahrenheitUnit := Fahrenheit

celsiusUnit.String()
// => °C
fahrenheitUnit.String()
// => °F
fmt.Sprint(celsiusUnit)
// Output: °C

2. نفّذ الواجهة Stringer للنوع Temperature

تتكون قيم Temperature من عدد صحيح ووحدة حرارة. ينبغي تنسيقها كما في الأمثلة أدناه.

لتحقيق ذلك، اجعل النوع Temperature يُنفّذ الواجهة Stringer بإضافة طريقة String إليه. ينبغي أن تُرجع هذه الطريقة سلسلة نصية تحتوي على القيمة العددية للحرارة ووحدة الحرارة مفصولتين بمسافة: <temperature> <unit>:

celsiusTemp := Temperature{
    degree: 21,
    unit: Celsius,
}
celsiusTemp.String()
// => 21 °C
fmt.Sprint(celsiusTemp)
// Output: 21 °C

fahrenheitTemp := Temperature{
    degree: 75,
    unit: Fahrenheit,
}
fahrenheitTemp.String()
// => 75 °F
fmt.Sprint(fahrenheitTemp)
// Output: 75 °F

3. نفّذ الواجهة Stringer للنوع SpeedUnit

بعد نقاشات مطوّلة، اتفق الفريق على أن وحدة سرعة الرياح ستكون إما KmPerHour أو MilesPerHour. ينبغي تنسيق القيم كما في الأمثلة أدناه.

لتحقيق ذلك، اجعل النوع SpeedUnit يُنفّذ الواجهة Stringer بإضافة طريقة String إليه. يجب أن تُرجع هذه الطريقة السلسلة النصية "km/h" إذا كانت وحدة السرعة كيلومترًا في الساعة أو "mph" إذا كانت وحدة السرعة ميلًا في الساعة:

mphUnit := MilesPerHour
mphUnit.String()
// => mph
fmt.Sprint(mphUnit)
// Output: mph

kmhUnit := KmPerHour
kmhUnit.String()
// => km/h
fmt.Sprint(kmhUnit)
// Output: km/h

4. نفّذ الواجهة Stringer للنوع Speed

تتكون قيم سرعة الرياح من عدد صحيح ووحدة سرعة. ينبغي تنسيقها كما في المثال أدناه.

لتحقيق ذلك، اجعل النوع Speed يُنفّذ الواجهة Stringer بإضافة طريقة String إليه. ينبغي أن تُرجع هذه الطريقة سلسلة نصية تحتوي على القيمة العددية للسرعة ووحدة السرعة مفصولتين بمسافة: <speed> <unit>:

windSpeedNow := Speed{
    magnitude: 18,
    unit: KmPerHour,
}
windSpeedNow.String()
// => 18 km/h
fmt.Sprintf(windSpeedNow)
// Output: 18 km/h

windSpeedYesterday := Speed{
    magnitude: 22,
    unit: MilesPerHour,
}
windSpeedYesterday.String()
// => 22 mph
fmt.Sprint(windSpeedYesterday)
// Output: 22 mph

5. نفّذ الواجهة Stringer للنوع MeteorologyData

تحدد بيانات الأرصاد الجوية الموقع ودرجة الحرارة واتجاه الرياح وسرعة الرياح والرطوبة. ينبغي تنسيقها كما في المثال أدناه:

لتحقيق ذلك، اجعل النوع MeteorologyData يُنفّذ الواجهة Stringer بإضافة طريقة String إليه. ينبغي أن تُرجع هذه الطريقة بيانات الأرصاد الجوية بالتنسيق التالي:

<location>: <temperature>, Wind <wind_direction> at <wind_speed>, <humidity>% Humidity
sfData := MeteorologyData{
    location: "San Francisco",
    temperature: Temperature{
        degree: 57,
        unit: Fahrenheit
    },
    windDirection: "NW",
    windSpeed: Speed{
        magnitude: 19,
        unit: MilesPerHour
    },
    humidity: 60
}

sfData.String()
// => San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
fmt.Sprint(sfData)
// Output: San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Go Exercism

مستعد لبدء علم الأرصاد الجوية؟

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