أساسيات المؤشرات في Go
جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 19 من 107.
إن pointer هو variable يخزّن عنوان memory لـ variable آخر. وبدلاً من الاحتفاظ بقيمة مباشرة، فإنه holds الموقع الذي توجد فيه تلك القيمة في memory. تُعدّ Pointers أساسية في Go وضرورية لمعالجة البيانات بكفاءة.
لإنشاء pointer، استخدم & operator للحصول على address الخاص بـ variable، واستخدم * operator لتعريف نوع pointer أو access إلى القيمة الموجودة في ذلك address.
x := 42
p := &x // p يحمل عنوان الذاكرة لـ x
fmt.Println(p) // 0xc000018030 (عنوان الذاكرة)
fmt.Println(*p) // 42 (القيمة في ذلك العنوان)يعني العامل & «address of» ويُعيد pointer. أمّا العامل *، عند استخدامه مع pointer، فيعني «القيمة عند» ويُسمّى إلغاء الإشارة. يمكنك أيضًا تعديل القيمة original من خلال pointer.
x := 10
p := &x
*p = 25 // تغيير القيمة عبر المؤشر
fmt.Println(x) // 25 (تم تغيير المتغير الأصلي)يُكتب نوع المؤشر بالشكل *T حيث إن T هو النوع الذي يشير إليه. يكون نوع المؤشر إلى int هو *int.
var p *int // يعلن عن مؤشر إلى int
x := 100
p = &x // p يشير الآن إلى xالقيمة الصفرية لـ pointer هي nil، ما يعني أنه يشير إلى لا شيء. تؤدي محاولة إلغاء الإشارة إلى nil pointer إلى حدوث ذعر وقت التشغيل، لذا احرص دائمًا على تهيئة pointers قبل استخدامها.
التحدي
سهللنَبْنِ مبدّل قيم بسيطًا يوضّح قوة pointers في modify variables من خلال memory addresses الخاصة بها.
ستُنظّم الكود عبر ملفين:
swap.go: أنشئ function باسمSwapValuesتأخذ two*intpointers كمعلمات. يجب أن تبدّل هذه function values التي تشير إليها هذه pointers؛ وبعد استدعائها، يجب أن تحتوي كل variable على original الخاص بالمتغير الآخر. لا تُرجع function أي شيء؛ بل تعدّل values مباشرةً من خلال pointers.main.go: اقرأ two integers من input، وخزّنهما في variables، ثم استخدم functionSwapValuesالخاصة بك لتبادل values بينهما. اطبع القيمتين قبل وبعد swap لإظهار change.
سيتم توفير input التالي:
- السطر 1: العدد الصحيح الأول
- السطر 2: العدد الصحيح الثاني
تنسيق الإخراج:
Before: a=[first] b=[second]
After: a=[first] b=[second]على سبيل المثال، عند إعطاء 10 و25، يجب أن يكون الإخراج:
Before: a=10 b=25
After: a=25 b=10Remember استخدام & operator عند تمرير variables الخاصة بك إلى function، واستخدام * operator داخل function للوصول إلى actual values وتعديلها.
جرّب بنفسك
package main
import "fmt"
func main() {
// اقرأ عددين صحيحين من الإدخال
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// اطبع القيم قبل التبديل
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: استدعِ دالة SwapValues مع مؤشرات إلى a و b
// تذكر استخدام عامل & لتمرير العناوين
// اطبع القيم بعد التبديل
fmt.Printf("After: a=%d b=%d\n", a, b)
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP في Go
الملفات الخارجيةمساحة العمل والـ Modules في Goالـ Packages والـ Importsالأسماء المصدرة مقابل غير المصدرةمقدمة إلى الـ OOP في Goالـ Structs كـ Classesتعريف الـ Methods في الـ Structsالـ Pointer Receivers مقابل الـ Value Receiversتهيئة الـ Structدوال الـ Constructorمراجعة - آلة حاسبة بسيطة4الواجهات
مقدمة في الواجهاتالتنفيذ الضمنيالواجهة كعقدالواجهة الفارغة (any)تأكيد النوع (Type Assertion)تبديل النوع (Type Switch)تركيب الواجهاتواجهات Stringer و Errorمراجعة - حاسبة الأشكال7التغليف
الحقول المصدرة وغير المصدرةالتغليف على مستوى الحزمةدوال الـ Getter والـ Setterإخفاء المعلومات في Goملخص - سجلات الطلاب10الأنواع العامة (Go 1.18+)
مقدمة في الأنواع العامةمعاملات الأنواعقيود الأنواعالـ Structs العامةحل بديل للـ Methods العامةملخص - المجموعات العامة13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy2تعمق في الأنواع و Structs
الأنواع الأساسية والمركبةتعريفات الأنواع المخصصةStruct TagsStructs مجهولةStructs متداخلةالقيم الصفرية والافتراضيةمراجعة - دفتر العناوين5التركيب بدلاً من الوراثة
لماذا لا تدعم Go الوراثةأساسيات تضمين الـ Structترقية الـ Methodتضمين عدة Structsالتضمين مقابل التجميعحجب الـ Methods المضمنةملخص - الهيكل الهرمي للموظفين8معالجة الأخطاء و OOP
واجهة errorأنواع الأخطاء المخصصةتغليف الأخطاء (fmt.Errorf)أخطاء Sentinelerrors.Is() و errors.As()Panic و Defer و Recoverملخص - File Parser11المكتبة القياسية والبرمجة كائنية التوجه (OOP)
io.Reader و io.Writerواجهة sort.Interfaceواجهة fmt.Stringerencoding/json مع Structsواجهة http.Handlerمراجعة - نماذج REST API14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبMiddleware كنمط مزين3المؤشرات والذاكرة
أساسيات المؤشرات في Goالمؤشرات إلى الـ Structsالتمرير بالقيمة مقابل التمرير بالمرجعدالة ()newGarbage Collection في Goملخص - بناء Linked List6تعدد الأشكال في Go
تعدد الأشكال عبر InterfacesDuck Typing في Goقواعد استيفاء الـ Interfaceمجموعات متعددة الأشكالحقن التبعيةمراجعة - معالج الدفع9التزامن والبرمجة كائنية التوجه (OOP)
أساسيات الـ Goroutinesالقنوات (Channels) والاتصالالقنوات المخزنة (Buffered) مقابل غير المخزنةجملة Selectsync.Mutex و sync.RWMutexsync.WaitGroupتصميم الـ Structs الآمنة للخيوط (Thread-Safe)مراجعة - Worker Poolتدرّب بنفسك: مترجم Go عبر الإنترنت