Skip to content

ثوابت Go

قيمة الثابت لا يمكن تغييرها أثناء التشغيل، بمجرد تعيينها لا يمكن تعديلها، وقيمتها يمكن أن تأتي فقط من:

  • القيم الحرفية
  • معرفات الثوابت الأخرى
  • تعابير الثوابت
  • تحويلات النوع التي نتائجها ثوابت
  • iota

الثوابت يمكن أن تكون فقط أنواع بيانات أساسية، ولا يمكن أن تكون:

  • أنواعاً أخرى غير الأنواع الأساسية مثل الهياكل والواجهات والشرائح والمصفوفات
  • القيمة المُرجعة من دالة

قيمة الثابت لا يمكن تعديلها، وإلا لن يتم الترجمة

التهيئة

تعريف الثابت يتطلب الكلمة المفتاحية const، يجب تهيئة الثابت بقيمة عند تعريفه، ويمكن حذف نوع الثابت، مثلاً:

go
const name string = "Jack" // قيمة حرفية

const msg = "hello world" // قيمة حرفية

const num = 1 // قيمة حرفية

const numExpression = (1+2+3) / 2 % 100 + num // تعبير ثابت

إذا تم التعريف فقط بدون تحديد قيمة، لن يتم الترجمة:

go
const name string

المُترجم سيُظهر خطأ:

missing init expr for name

يمكن استخدام () لتجميع تعريفات الثوابت المتعددة لتحسين القراءة، ويمكن وجود عدة () للتنظيم:

go
const (
   Count = 1
   Name  = "Jack"
)

const (
   Size = 16
   Len  = 25
)

في نفس مجموعة الثوابت، الثوابت التي تلي ثابتاً تم تعيينه يمكن عدم تعيينها، وقيمتها الافتراضية هي قيمة السابق، مثلاً:

go
const (
  A = 1
  B // 1
  C // 1
  D // 1
  E // 1
)

iota

iota هو معرف ثابت مدمج، يُستخدم عادةً لتمثيل رقم صحيح غير مُنمذج في تعريف الثوابت، ويُستخدم عموماً داخل الأقواس:

go
const iota = 0

انظر بعض حالات الاستخدام:

go
const (
   Num = iota // 0
   Num1 // 1
   Num2 // 2
   Num3 // 3
   Num4 // 4
)

يمكن أيضاً كتابته هكذا:

go
const (
   Num = iota*2 // 0
   Num1 // 2
   Num2 // 4
   Num3 // 6
   Num4 // 8
)

يمكن أيضاً:

go
const (
   Num = iota << 2*3 + 1 // 1
   Num1 // 13
   Num2 // 25
   Num3 = iota // 3
   Num4 // 4
)

من خلال الأمثلة أعلاه،可以发现، iota يتزايد، أول ثابت يستخدم تعبير قيمة iota، وفقاً لتغير رقم التسلسل سيتم تعيينه تلقائياً للثوابت اللاحقة، حتى يتم إعادة تعيينه بـ const جديد، هذا الرقم هو في الواقع رقم السطر النسبي للكود، نسبة إلى سطر البداية للمجموعة الحالية، انظر المثال التالي:

go
const (
  Num  = iota<<2*3 + 1 // 1 السطر الأول
  Num2 = iota<<2*3 + 1 // 13 السطر الثاني
  _ // 25 السطر الثالث
  Num3 //37 السطر الرابع
  Num4 = iota // 4 السطر الخامس
  _ // 5 السطر السادس
  Num5 // 6 السطر السابع
)

المثال يستخدم المعرف المجهول _ ليحتل موضع سطر، يمكن ملاحظة أن قيمة iota هي في الأساس فرق السطر الذي يوجد فيه iota نسبة إلى أول سطر في مجموعة const الحالية. ومجموعات const المختلفة لا تؤثر على بعضها البعض.

التعدادات

لغة Go لم تصمم نوع بيانات منفصل للتعدادات، على عكس اللغات الأخرى التي عادةً يكون لديها enum للتعبير عن ذلك. عموماً في Go، يتم تنفيذ التعدادات من خلال نوع مخصص + const + iota، مثال بسيط:

go
type Season uint8

const (
  Spring Season = iota
  Summer
  Autumn
  Winter
)

هذه التعدادات هي في الواقع أرقام، وGo لا تدعم تحويلها مباشرة إلى سلاسل نصية، لكن يمكننا إضافة طريقة للنوع المخصص لإرجاع شكلها النصي، من خلال تنفيذ واجهة Stringer:

go
func (s Season) String() string {
  switch s {
  case Spring:
    return "spring"
  case Summer:
    return "summer"
  case Autumn:
    return "autumn"
  case Winter:
    return "winter"
  }
  return ""
}

هذا تنفيذ بسيط للتعدادات. يمكنك أيضاً استخدام الأداة الرسمية Stringer لتوليد التعدادات تلقائياً.

لكن لها العيوب التالية:

  • النوع غير آمن، لأن Season نوع مخصص، يمكن تحويل أرقام أخرى إلى هذا النوع من خلال تحويل النوع القسري

    go
    Season(6)
  • مُعقد، الشكل النصي يحتاج إلى تنفيذه بنفسك

  • قدرة تعبيرية ضعيفة، لأن const يدعم فقط أنواع البيانات الأساسية، لذا قيم هذه التعدادات يمكن أن تكون فقط سلاسل نصية وأرقام

لماذا لا يتم دعم التعدادات على مستوى اللغة هو شيء لا أفهمه شخصياً، أعتقد أن هذا بالتأكيد إيجابياته أكثر من سلبياته.

Golang تم تحريره بواسطة www.golangdev.cn