Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

واجهات Stringer و Error

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 32 من 107.

تحدد مكتبة Go القياسية واجهتين ستستخدمهما باستمرار: fmt.Stringer و error. كلاهما واجهتان بسيطتان أحاديتا الطريقة تمنحان أنواعك تكاملاً قوياً مع وظائف Go المدمجة.

توجد واجهة Stringer في حزمة fmt وتتطلب طريقة واحدة فقط:

type Stringer interface {
    String() string
}

عندما تقوم بتنفيذ String() على النوع الخاص بك، فإن دوال مثل fmt.Println تستخدمه تلقائيًا لعرض قيمتك:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice (30 عاماً)
}

تُعد واجهة error بسيطة بنفس القدر، حيث تتطلب دالة Error() تُعيد سلسلة نصية:

type error interface {
    Error() string
}

أي نوع يحتوي على دالة Error() يمكن استخدامه كقيمة خطأ في Go. يتيح لك ذلك إنشاء أنواع أخطاء مخصصة مع سياق إضافي:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: تنسيق غير صالح
}

توضح هاتان الواجهتان فلسفة لغة Go: واجهات صغيرة ومركزة تتيح سلوكاً قوياً من خلال التنفيذ الضمني.

challenge icon

التحدي

سهل

لنقم ببناء نظام لمراقبة درجة الحرارة يستخدم واجهتي Stringer و error لتوفير مخرجات قابلة للقراءة ومعالجة هادفة للأخطاء.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • temperature.go: قم بإنشاء هيكل Temperature يحتوي على حقول Value (float64) و Unit (string). قم بتنفيذ طريقة String() بحيث تعرض درجة الحرارة بتنسيق سهل القراءة عند طباعتها. قم أيضاً بإنشاء هيكل TemperatureError يحتوي على حقول Temp (float64) و Reason (string)، وقم بتنفيذ طريقة Error() لتقديم رسائل خطأ وصفية.
  • main.go: قم بإنشاء دالة تسمى ValidateTemperature تأخذ Temperature وتعيد خطأً إذا كانت درجة الحرارة غير صالحة. تكون درجة الحرارة غير صالحة إذا كانت أقل من الصفر المطلق (-273.15 للدرجة المئوية، -459.67 للفهرنهايت). إذا كانت صالحة، تعيد الدالة nil. اقرأ بيانات درجة الحرارة من المدخلات، وأنشئ Temperature، وقم بالتحقق من صحتها، واطبع المخرجات المناسبة.

سيتم توفير المدخلات التالية:

  • السطر 1: قيمة درجة الحرارة (float)
  • السطر 2: الوحدة (C للدرجة المئوية أو F للفهرنهايت)

يجب أن تعيد طريقة String() الخاصة بك التنسيق التالي:

[Value] degrees [Unit]

حيث Unit هي الكلمة الكاملة "Celsius" أو "Fahrenheit" بناءً على المدخلات.

يجب أن تعيد طريقة Error() الخاصة بك التنسيق التالي:

invalid temperature [Temp]: [Reason]

إذا كانت درجة الحرارة صالحة، اطبع Temperature باستخدام fmt.Println (والتي ستستخدم طريقة String() الخاصة بك). إذا كانت غير صالحة، اطبع الخطأ (والذي سيستخدم طريقة Error() الخاصة بك).

على سبيل المثال، إذا كانت المدخلات 25.5 و C، يجب أن تكون مخرجاتك:

25.5 degrees Celsius

وإذا كانت المدخلات -500 و F، يجب أن تكون مخرجاتك:

invalid temperature -500: below absolute zero

استخدم "below absolute zero" كسبب (reason) عندما تكون درجة الحرارة منخفضة جداً.

ورقة مرجعية

تُعرف مكتبة Go القياسية واجهتين أساسيتين: fmt.Stringer و error.

واجهة Stringer

تتطلب واجهة Stringer من حزمة fmt طريقة واحدة:

type Stringer interface {
    String() string
}

عندما تقوم بتنفيذ String() على النوع الخاص بك، فإن دوال مثل fmt.Println تستخدمها تلقائيًا:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice (30 years old)
}

واجهة error

تتطلب واجهة error طريقة Error() التي تُرجع سلسلة نصية (string):

type error interface {
    Error() string
}

يمكن استخدام أي نوع يحتوي على طريقة Error() كقيمة خطأ، مما يسمح بأنواع أخطاء مخصصة مع سياق إضافي:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: invalid format
}

جرّب بنفسك

package main

import (
	"fmt"
)

// ValidateTemperature يتحقق مما إذا كانت درجة الحرارة صالحة
// يعيد خطأ إذا كانت درجة الحرارة أقل من الصفر المطلق
// الصفر المطلق: -273.15 للدرجة المئوية، -459.67 للفهرنهايت
func ValidateTemperature(t Temperature) error {
	// TODO: تنفيذ منطق التحقق
	// التحقق مما إذا كانت درجة الحرارة أقل من الصفر المطلق بناءً على الوحدة
	// إرجاع TemperatureError إذا كانت غير صالحة، و nil إذا كانت صالحة
	return nil
}

func main() {
	var value float64
	var unit string
	fmt.Scanln(&value)
	fmt.Scanln(&unit)

	// TODO: إنشاء هيكل Temperature بالقيم المدخلة

	// TODO: التحقق من صحة درجة الحرارة باستخدام ValidateTemperature

	// TODO: إذا كان هناك خطأ، قم بطباعة الخطأ
	// خلاف ذلك، قم بطباعة درجة الحرارة (والتي ستستخدم طريقة String())
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming