لغة البرمجة GO الجزء الثاني – المتغيرات

في جميع لغات البرمجة نستخدم المتغيرات أو المتحولات لتخزين البيانات في الذاكرة . ويمكن تعريف المتحولات في لغة البرمجة GO بأكثر من طريقة.

تعرفنا في الجزء الأول على بعض ميزات لغة البرمجة GO وأيضاً كيفية تجهيز بيئة البرمجة وكتابة برنامج بسيط وتحويله إلى ملف تنفيذي جاهز للاستخدام.
والآن سنتعرف على أهم الأساسيات في لغة البرمجة و هي المتحولات أو المتغيرات وأنواعها.
لنبدأ أولا بشرح أنواع البيانات أو ما يسمى Data Types والمقصود بها أنواع المتغيرات حسب طريقة تخزينها في الذاكرة.
و في لغة البرمجة GO لدينا الأنواع التالية:

Bool نوع البيانات الخاص لتخزين القيم المنطقية true / false

integers وهي نوع البيانات الخاص لتخزين الأعداد الصحيحة مثلا : 23
ولدينا في لغة البرمجة GO أكثر من نوع من الأعداد الصحيحة. وهي:
– int : عدد صحيح بطول 32 بت أو 64 بت حسب نوع نظام التشغيل.
– int8 : عدد صحيح بطول واحد بايت لتخزين قيم بين -128 و 127
– int16 : عدد صحيح بطول 16 بت لتخزين قيم بين -32768  و 327687
– int32 : عدد صحيح بطول 32 بت
– int64 : عدد صحيح بطول 64 بت

Float نوع البيانات الخاص لتخزين الارقام العشرية مثلا : 10.25
ولدينا نوعين منها :
– float32 : عدد حقيقي لتخزين الأرقام العشرية بطول 32 بت
– float64 : عدد حقيقي لتخزين أرقام عشرية بطول 64 بت

String نوع البيانات الخاص لتخزين سلسلة من الأحرف الأبجدية مثلا Hello

هذه أهم الأنواع المستخدمة في لغة البرمجة GO .

المتغيرات Variables

في جميع لغات البرمجة نستخدم المتغيرات أو المتحولات لتخزين البيانات في الذاكرة .
ويمكن تعريف المتحولات في لغة البرمجة GO بأكثر من طريقة.

1- باستخدام الكلمة var .
حيث نكتب بعدها إسم المتحول ثم نوع المتحول . وبعدها يمكن أن نضع قيمة افتراضية للمتحول لحظة إنشائه كما يلي:

var x int = 10
var y int
var z = 55

var str string = "Hello"
var h = "Hi"

var aa   // خطأ

المتحول x تم تعريفه على أنه عدد صحيح . ووضعنا فيه القيمة 10 مباشرة عند تعريفه.

المتحول y تم تعريفه على أنه عدد صحيح. ولكن لم نضع فيه قيمة افتراضية.
في هذه الحالة تكون قيمته تساوي الصفر .

المتحول z تم تعريفه بدون تحديد نوعه. ولكن قمنا بوضع الرقم 55 فيه . وهي قيمة عدد صحيح.
لذلك يتم اعتبار المتحول z على انه من نوع int بشكل تلقائي

المتحول str قمنا بتعريفه على أنه نص من نوع string . ووضعنا فيه قيمة أولية وهي الكلمة Hello .
وهو عبارة عن سلسلة من الأحرف مخزنة بجانب معضها البعض في الذاكرة .

المتحول h أيضا قمنا بتعريفه بدون تحديد نوعه. ولكن وضعنا فيه نص باللغة الانكليزية. لذلك يتم اعتبار قيمته من النوع string بشكل تلقائي.

أما المتحول aa فقد قمنا بتعريفه بدون تحديد نوعه. وكذلك لم نضع فيه أي قيمة. وفيهذه الحالة لايمكن معرفة نوع المتحول مسبقاً من قبل لغة البرمجة.
لذلك سيظهر لدينا خطأ خلال تنفيذ البرنامج.

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

2 – تعريف المتغيرات بالإسناد :

في هذه الطريقة نقوم فقط بكتابة اسم المتحول ثم نكتب نقطتين فوق بعضها تتبعها إشارة المساواة كما يلي:

x := 25
a := "hello"

في هذه الحالة لابد من وضع قيمة افتراضية في المتحول عند تعريفه. وذلك لتتمكن لغة البرمجة من معرفة نوع هذا المتحول.
لهذا السبب يكون المتحول x عبارة عن عدد صحيح لأننا وضعنا فيه القيمة 25
وكذلك المتحول a هو عبارة عن نص من نوع string

3 – تعريف المتحولات في سطر واحد

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

 var a, b, c int = 1, 3, 5

 var i, j = 10, "Hi"

 k, m := 15, "Okay"

هنا لدينا في السطر الأول تعريف المتحولات a و b و c على أنها من نفس النوع int
ووضعنا فيها القيم الموجودة بعد اشارة المساواة بحيث القيمة الأولى للمتحول الأول , والثانية للثاني و هكذا.

أما في السطر الثاني قمنا بتعريف المتحولات i و j بنفس الطريقة ولكن بدون تحديد نوع المتحول.
وفي هذه الحالة كما قلنا يتم تحديد نوع المتحول حسب القيمة التي نضعها فيه.
وهنا القيمة 10 في المتحول i تجعله من نوع عدد صحيح.
والقيمة Hi في المتحول j تجعله من نوع نص string

وفي السطر الثالث نطبق نفس القاعدة ولكن باستخدام طريقة الاسناد لتعريف المتحولات.
حيث k هو رقم صحيح قيمته 15 والمتحول m هو نص قيمته Okay

4 – تعريف المتحولات بشكل مجمع ضمن Block

في هذه الطريقة نستخدم أيضا الكلمة var ولكن نضع بعدها جميع المتحولات بين قوسين كما في الشكل التالي:

var (
     X int
     y int = 1
     z string = "hello"
   )

كما نلاحظ أن هذه الطريقة لا تختلف كثيراً عن ما سبق. لكن تفيد في ترتيب الكود ضمن البرنامج ليصبح أكثر وضوحاً من حيث القرائة.
كما أننا هنا استخدمنا كلمة var مرة واحدة مما يقلل من التكرار

مثال عملي:

لنقوم بتطبيق ما تعلمناه بشكل عملي وذلك بكتابة برنامج جديد في بيئة البرمجة VSCode ونحفظ هذا البرنامج في ملف بإسم vars.go ونكتب فيه الكود البسيط التالي:

package main

import ("fmt")

func main() {
  var x int = 10
  var y int
  var z = 55
  k := 123

  
  var str1 string = "Hello"
  var str2 = "Hi"
  str3 := "Okay"

  fmt.Println(x)
  fmt.Println(y)
  fmt.Println(z)
  fmt.Println(k)

  fmt.Println(str1)
  fmt.Println(str2)
  fmt.Println(str3)
}

كما تعلمنا سابقاً في الجزء الأول, نكتب الأمر التالي في موجه الأوامر لتنفيذ البرنامج :

D:\Tutorials\GO\helloGo>go run vars.go  
10
0    
55   
123  
Hello
Hi   
Okay 

كما نلاحظ أن نتيجة تنفيذ البرنامج هو طباعة محتوى المتغيرات على الشاشة حسب ترتيب أوامر الطباعة في البرنامج.
حيث مثلا أول متحول هو x وقيمته تساوي 10
وثاني متحول هو y وقيمته تساوي 0 لأننا لم نضع فيه قيمة افتراضية.
وهكذا قيم جميع المتحولات ظاهرة على الشاشة بعد تنفيذ البرنامج

الثوابت Constants

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

وهي متغيرات أو متحولات يمكن أن تكون من أي نوع ويتم تعريفها بنفس الطريقة السابقة ولكن بدلاً من كلمة var نستخدم الكلمة const

لنأخذ المثال التالي ونعرف بعض الثوابت:

const x = 30

const y int = 5

const z string = "hi"

  • الثابت x قمنا بتعريفه ووضعنا فيه القيمة 30 لذلك هو من نوع int
  • الثابت y حددنا نوعه خلال تعريفه على انه من نوع int
  • الثابت z قمنا بتعريفه من نوع string ووضعنا فيه القيمة hi

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

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

طباعة المتحولات على الشاشة

استخدمنا في المثال السابق التابع Println من الحزمة fmt لطباعة محتوى المتحولات على الشاشة.
لكن طباعة المحتوى فقط لا يعطي معلومات واضحة خلال كتابة البرامج. لذلك سنتعلم هنا كيف نستفيد من جميع ميزات التابع Println

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

package main
import ("fmt")

func main() {
  var i int = 5
  var str string = "ABC"

  fmt.Println(" i = ", i)

  fmt.Println(" Str = ", str)

}

نقوم بتنفيذ هذا البرنامج لنرى النتيجة على الشاشة كما يلي:

D:\Tutorials\GO\helloGo>go run vars.go
 i =  5
 Str =  ABC

ثانيا : التابع Printf يقوم بطباعة المتحولات على أساس صيغة محددة نكتبها على شكل نص حسب رغبتنا وضمن قواعد محددة.
وهذه الصيغة أو ما يسمى Format تكون هي أول قيمة نضعها ضمن دخل التابع, ثم يليها باقي المتحولات.

لنفرض أننا نريد أن نطبع قيمة المتحول x الذي هو عدد صحيح . ونريد أن نطبع قبلها كلمة X is مثلا .
في هذه الحالة نكتب التابع كما يلي:

fmt.Printf("X is: %v", x)

المعامل الأول للتابع هو الصيغة. وهي عبارة عن نص يتم طباعته على الشاشة كما هو , لكن الرمز %v لا يتم طباعته. وإنما يتم استبداله بقيمة أول متحول بعد الصيغة.
وبالتالي اذا كانت قيمة x هي 55 مثلا سوف تكون النتيجة على الشاشة هي:

X is: 55

أما لو كان الرمز %v مكرر أكثر من مرة. عندها يكون في المرة الأولى يعبر عن المعامل الأول بعد الصيغة , وفي المرة الثانية يتم استبداله بالمعامل الثاني, وهكذا.

المثال التالي يوضح ذلك:

  var x int = 55
  var y int = 88


  fmt.Printf("X is: %v  and Y is: %v", x, y)

نتيجة تنفيذ هذا الأمر هو طباعة السطر التالي على الشاشة:

X is: 55  and Y is: 88

يمكن استخدام هذا التابع بهذه الطريقة لطباعة محتوى أي نوع من أنواع المتحولات وليس فقط الأرقام.
كما يمكن أيضا طباعة نوع هذا المتحول. وذلك باستخدام الرمز %T بدلا من %v

لنأخذ المثال السابق ونقوم بطباعة نوع المتحول x كما يلي:

var x int = 55 

fmt.Printf("X value is: %v  and its type is: %T", x, x)

هنا لدينا ضمن نص الصيغة رمزين. الأول لطباعة قيمة أول متحول وهو هنا x
والثاني لطباعة نوع ثاني متحول, وأيضا هو المتحول x
والنتيجة هي طباعة ما يلي على الشاشة:

X value is: 55  and its type is: int

أيضا يمكن استخدام التابع Printf لطباعة المتحولات بأشكال متعددة. حيث يوجد رموز خاصة لطباعة الأرقام الصحيحة والأرقام العشرية وغيرها

على سبيل المثال عندما نريد طباعة رقم صحيح بشكل رقم بالنظام الثنائي نستخدم الرمز %b .
أما لطباعة رقم في النظام السداسي عشر نستخدم الرمز %x .
المثال التالي يوضح بعض هذه الرموز بشكل أفضل:

  var x int = 10

  fmt.Printf("x in decimal  %d\n", x)
  fmt.Printf("x in binary   %b\n", x)
  fmt.Printf("x in octal    %o\n", x)
  fmt.Printf("x in hex (lower-case) %x\n", x)
  fmt.Printf("x in hex (upper-case) %X\n", x)

هنا قمنا بتعريف متحول ووضعنا فيه قيمة العدد الصحيح 10
ثم قمنا بطباعة قيمة المتحول كما هو حسب النظام العشري باستخدام الرمز %d
وطبعنا قيمة نفس المتحول حسب النظام الثنائي باستخدام الرمز %b
وكذلك طبعنا قيمته حسب النظام الثماني باستخدام الرمز %o
أما في النظام السداسي عشر نستخدم الرمز %x

ونتيجة التنفيذ هي طباعة ما يلي على الشاشة:

x in decimal  10
x in binary   1010
x in octal    12
x in hex (lower-case) a
x in hex (upper-case) A

هكذا نكون قد تعلمنا كيفية تعريف المتحولات وتحديد ماتحتويه من قيم وطباعتها على الشاشة.

وبذلك نكون قد وصلنا إلى نهاية هذا الجزء من الدورة.