دروس الوحدة (4/5)
واجهة سترينجر
ربما تكون fmt.Stringer هي الواجهة القياسية الأكثر استخدامًا على الإطلاق
مكتبة Go القياسية. إنه العرض المثالي للقوة
من الواجهات الصغيرة.
تعريف
type Stringer interface {
String() string
}توقيع واحد. أي نوع يحدد String() string يرضي
ذلك. ويتعرف fmt على هذه الواجهة: عندما تقوم بتمرير قيمة إلى
fmt.Print*، إذا تم تنفيذ Stringer، فإن نتيجة String()
يتم استخدامه بدلاً من التمثيل الافتراضي.
مثال
type Point struct{ X, Y int }
func (p Point) String() string {
return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}
fmt.Println(Point{1, 2}) // (1,2)
fmt.Printf("%v %s\n", Point{3, 4}, Point{5, 6})
// (3,4) (5,6)تتم طباعة نفس القيمة بتنسيق مخصص في %v، %s، Println،
Sprint، log، وما إلى ذلك. كل ذلك فقط من خلال تحديد طريقة واحدة.
عندما يكون من المنطقي
- الأنواع التي تمثل المجال (المعرفات، والرموز، والإحداثيات، والتعدادات).
- أخطاء في التمثيل الذي يمكن قراءته بواسطة الإنسان (راجع الدرس التالي في
error). - الأنواع التي تقوم بتسجيل الدخول إليها كثيرًا والتي تريد تنسيقًا ثابتًا لها.
ليس لكل شيء: إذا كان النوع بسيطًا والتمثيل الافتراضي على ما يرام، لا تضيف الضوضاء.
أنواع التعداد: النمط الشائع مع iota
type Status int
const (
OK Status = iota
WARN
ERR
)
func (s Status) String() string {
switch s {
case OK: return "OK"
case WARN: return "WARN"
case ERR: return "ERR"
default: return "UNKNOWN"
}
}
fmt.Println(OK, WARN, ERR) // OK WARN ERRبدون String()، ستتم طباعة fmt.Println(OK) 0. مع String()،
يطبع الاسم الرمزي. stringer
تقوم الأداة بإنشاء هذا النمط تلقائيًا.
احترس من العودية اللانهائية
type T int
func (t T) String() string {
return fmt.Sprintf("%d", int(t)) // OK: cast to int breaks the recursion
}سترينجر على جهاز استقبال المؤشر
إذا كان String() يحتوي على جهاز استقبال للمؤشر، فإن *T فقط يرضي Stringer.
باستخدام fmt.Println(t) (قيمة)، ينظر Go إلى مجموعة الأساليب T،
لم يجده، ويستخدم التنسيق الافتراضي. لتجنب هذا، قيمة
يتم استخدام جهاز الاستقبال عادةً لـ String() (إنه "عرض"؛ لكنه ليس كذلك
تعديل أي شيء).
جربه
قم بتطبيق String() على النقطة بحيث ترجع (X,Y).
إظهار التلميح
استخدم fmt.Sprintf لتنسيق الحقول.
الحل متاح بعد 3 من المحاولات
قم بتنفيذ String() على نوع الحالة (int): 0 → 'OK'، 1 → 'WARN'، وإلا → 'ERR'.
إظهار التلميح
التبديل على قيمة المتلقي. تذكر أن توفر الافتراضي.
الحل متاح بعد 3 من المحاولات
ما هو التوقيع الذي يجب أن تكون عليه الطريقة لإرضاء fmt.Stringer؟
func (x T) ??? {}خلاصة
- محمي_INLINE_29.
- يؤدي تنفيذه إلى تغيير كيفية تمثيل
fmt.Print*للنوع. - اصطلاحي للتعدادات (
iota)، وأنواع المجال، والرموز/المعرفات. - لا تتصل أبدًا بـ
fmt.Sprintf("%s", t)علىtداخلString()(العودة). - الاصطلاح: مستقبل القيمة لـ
String()(لا يوجد تغيير، يتجنب "مفاجآت مجموعة الطريقة").