المتغيرات وأنواع البيانات

تخيّل أنك تطبخ في المطبخ: المتغيرات هي صناديق تخزين مُعلّمة — الملصق هو الاسم، والصندوق يحتوي البيانات؛ أنواع البيانات هي أشكال الصناديق — الصناديق الدائرية تдерж الحساء، والمربعة تдерж الأطباق، ولا يمكنك خلطها. Go صارمة جداً في إدارة "الصناديق": يجب أن تعلن أي صندوق (نوع) تحتاجه، أي محتوى تضعه (إسناد)، وحتى الصناديق الفارغة لها محتوى افتراضي (قيم صفرية).


1. المفاهيم الأساسية

1.1 إعلان المتغيرات: var مقابل :=

يقدم Go طريقتين لإعلان المتغيرات:

الطريقة الصياغة حالة الاستخدام النطاق
var var name int متغيرات على مستوى الحزمة، أنواع صريحة داخل/خارج الدوال
الإعلان المختصر := name := 10 متغيرات محلية، استنتاج النوع داخل الدوال فقط

الاختلافات الرئيسية:

1.2 أنواع البيانات الأساسية

الفئة النوع الوصف مثال
عدد صحيح int، int8، int16، int32، int64 أعداد صحيحة مُوقّعة var a int = 42
عدد صحيح غير مُوقّع uint، uint8، uint16، uint32، uint64 أعداد غير سالبة var b uint = 100
عدد عشري float32، float64 أعداد عشرية (الافتراضي float64) var c float64 = 3.14
منطقي bool true / false var d bool = true
نص string تسلسل بايتات غير قابل للتغيير var e string = "hello"
بايت byte اسم مستعار لـ uint8، يمثل بايتاً واحداً var f byte = 'A'
حرف Unicode rune اسم مستعار لـ int32، يمثل نقطة كود Unicode واحدة var g rune = 'ع'

أنواع تعتمد على المنصة: int و uint هما 32-بت على أنظمة 32-بت و 64-بت على أنظمة 64-بت. في التطوير اليومي، int كافية في معظم الحالات.

1.3 آلية القيم الصفرية

عندما يُعلن متغير في Go بدون إسناد، يتم تهيئته تلقائياً إلى قيمة صفرية، وليس null أو غير معرّف:

النوع القيمة الصفرية
عدد صحيح (int، uint، إلخ) 0
عدد عشري (float32، float64) 0.0
منطقي (bool) false
نص (string) "" (نص فارغ)
مؤشر، slice، map، channel، دالة، واجهة nil

هذه آلية أمان في Go — لن تحصل أبداً على متغير "بلا قيمة"، مما يتجنب العديد من أخطاء المؤشرات الفارغة.

1.4 الثوابت و iota

1.5 التحويل بين الأنواع

Go لا تدعم التحويل الضمني بين الأنواع؛ يجب تحويل الأنواع المختلفة بشكل صريح:

GO
var i int = 42
var f float64 = float64(i) // int → float64
var u uint = uint(f)        // float64 → uint

1.6 إخراج حزمة fmt المنسق

fmt هي حزمة التنسيق الأكثر استخداماً في Go. الدوال الرئيسية:

الدالة الغرض مثال
fmt.Println طباعة مع سطر جديد fmt.Println("hello")
fmt.Printf طباعة منسقة (بدون سطر جديد) fmt.Printf("value=%d", 42)
fmt.Sprintf تنسيق إلى نص (بدون طباعة) s := fmt.Sprintf("%d", 42)

مواصفات التنسيق الشائعة: %d (عدد صحيح)، %f (عشري)، %s (نص)، %t (منطقي)، %T (نوع)، %v (قيمة عامة)، %q (نص مُقتبس).


2. الصياغة والاستخدام الأساسي

إعلان المتغيرات

GO
// الطريقة 1: إعلان var (داخل/خارج الدوال)
var name string       // إعلان، قيمة صفرية ""
var age int = 25      // إعلان مع إسناد
var score = 98.5      // استنتاج النوع كـ float64

// الطريقة 2: الإعلان المختصر := (داخل الدوال فقط)
city := "New York"    // إعلان مع إسناد، يُستنتج كـ string
count := 100          // استنتاج النوع كـ int

// إعلان مجمع
var (
    width  int     = 10
    height int     = 20
    area   float64
)
💡 نصيحة: إذا أعلنت متغيراً بـ var ولم تستخدمه، سيعطي مترجم Go خطأ declared and not used. هذه فلسمة تصميم Go: لا يُسمح بコード ميت. نفس الشيء ينطبق على الإعلان المختصر :=.

إعلان الثوابت

GO
// ثابت واحد
const Pi = 3.14159
const Language string = "Go"

// ثوابت مجمعة + تعداد iota
const (
    Sunday    = iota // 0
    Monday           // 1
    Tuesday          // 2
    Wednesday        // 3
    Thursday         // 4
    Friday           // 5
    Saturday         // 6
)
💡 نصيحة: iota صالح فقط داخل كتلة const ويتزايد تلقائياً بمقدار 1 لكل سطر جديد. إذا استُخدم _ لتخطي سطر، فإن iota لا يزال يتزايد.

التحويل بين الأنواع

GO
var i int = 100
var f float64 = float64(i)  // تحويل صريح: int → float64
var s string = string(rune(i)) // int → rune → string (ملاحظة: لا يحول الرقم إلى نص)
// الطريقة الصحيحة لتحويل عدد إلى نص:
s2 := fmt.Sprintf("%d", i)  // "100"
💡 نصيحة: string(65) ينتج الحرف "A" (كود ASCII)، وليس "65". لتحويل عدد إلى نص عشري، استخدم fmt.Sprintf أو strconv.Itoa.


3. أمثلة الكود

مثال 1: الاستخدام الأساسي (الصعوبة ⭐)

السيناريو: إعلان متغيرات بأنواع مختلفة، وطباعة قيمها وأنواعها.

GO
package main

import "fmt"

func main() {
    // ========== إعلان المتغيرات ==========

    // 1. إعلان var + نوع صريح
    var name string = "Alice"
    var age int = 28

    // 2. إعلان var + استنتاج النوع (المترجم يستنتج النوع من القيمة)
    salary := 15000.5 // يُستنتج كـ float64

    // 3. إعلان متغير مختصر (الأكثر شيوعاً)
    isEmployed := true
    city := "New York"

    // 4. عرض القيم الصفرية — إعلان بدون إسناد
    var defaultInt int        // قيمة صفرية: 0
    var defaultFloat float64  // قيمة صفرية: 0
    var defaultBool bool      // قيمة صفرية: false
    var defaultString string  // قيمة صفرية: ""

    // ========== طباعة المخرجات ==========
    fmt.Println("=== معلومات شخصية ===")
    fmt.Printf("الاسم: %s (النوع: %T)\n", name, name)
    fmt.Printf("العمر: %d (النوع: %T)\n", age, age)
    fmt.Printf("الراتب: %.1f (النوع: %T)\n", salary, salary)
    fmt.Printf("موظف: %t (النوع: %T)\n", isEmployed, isEmployed)
    fmt.Printf("المدينة: %s (النوع: %T)\n", city, city)

    fmt.Println("\n=== عرض القيم الصفرية ===")
    fmt.Printf("قيمة int الصفرية:    %d\n", defaultInt)
    fmt.Printf("قيمة float64 الصفرية: %v\n", defaultFloat)
    fmt.Printf("قيمة bool الصفرية:   %t\n", defaultBool)
    fmt.Printf("قيمة string الصفرية: %q\n", defaultString) // %q يُظهر النص مُقتبساً
}
▶ جرّب الكود

المخرجات:

TEXT
=== معلومات شخصية ===
الاسم: Alice (النوع: string)
العمر: 28 (النوع: int)
الراتب: 15000.5 (النوع: float64)
موظف: true (النوع: bool)
المدينة: New York (النوع: string)

=== عرض القيم الصفرية ===
قيمة int الصفرية:    0
قيمة float64 الصفرية: 0
قيمة bool الصفرية:   false
قيمة string الصفرية: ""

النقاط الرئيسية:


مثال 2: الاستخدام المتوسط (الصعوبة ⭐⭐)

السيناريو: استخدام الثوابت و iota لتعريف التعدادات، والتحويل العملي بين الأنواع.

GO
package main

import "fmt"

// ========== تعداد iota: تعريف صلاحيات الأدوار ==========

type Role int // نوع مخصص مع int كنوع أساسي

const (
    Guest    Role = iota // 0: زائر
    Member               // 1: عضو
    Admin                // 2: مشرف
    SuperAdmin           // 3: مشرف عام
)

// تنفيذ طريقة String() لـ Role لسهولة الطباعة
func (r Role) String() string {
    names := [...]string{"زائر", "عضو", "مشرف", "مشرف عام"}
    if int(r) < len(names) {
        return names[r]
    }
    return "دور غير معروف"
}

// ========== استخدام iota المتقدم: أعلام الصلاحيات بالبتات ==========

type Permission int

const (
    Read    Permission = 1 << iota // 1 (001)
    Write                          // 2 (010)
    Execute                        // 4 (100)
)

// ========== التحويل بين الأنواع عملياً ==========

func main() {
    // --- استخدام تعداد iota ---
    var userRole Role = Admin
    fmt.Printf("دور المستخدم: %s (القيمة: %d)\n", userRole, userRole)

    // --- تركيب الصلاحيات بالبتات ---
    userPerm := Read | Write // صلاحيات مركبة: قراءة + كتابة = 3 (011)
    fmt.Printf("\nقيمة صلاحيات المستخدم: %d (ثنائي: %03b)\n", userPerm, userPerm)
    fmt.Printf("هل لديه صلاحية القراءة؟ %t\n", userPerm&Read != 0)
    fmt.Printf("هل لديه صلاحية التنفيذ؟ %t\n", userPerm&Execute != 0)

    // --- التحويل بين الأنواع ---
    var temperature float64 = 36.6
    var intTemp int = int(temperature) // float64 → int (يقطع، لا يُقرب)
    fmt.Printf("\nدرجة حرارة الجسم: %.1f°م → الجزء الصحيح: %d\n", temperature, intTemp)

    // عدد → نص (طريقتان)
    var code int = 65
    char := string(rune(code))      // الطريقة 1: تحويل إلى حرف Unicode المقابل → "A"
    numStr := fmt.Sprintf("%d", code) // الطريقة 2: تحويل إلى نص عشري → "65"
    fmt.Printf("العدد %d → الحرف: %s، النص: %q\n", code, char, numStr)

    // --- النصوص والبايتات/الأحرف ---
    s := "Hello,عالم"
    fmt.Printf("\nالنص %q الطول: %d بايت\n", s, len(s))
    fmt.Println("الiterate بايت ببايت (غير مُوصى به لـ CJK):")
    for i := 0; i < len(s); i++ {
        fmt.Printf("  [%d] %d %c\n", i, s[i], s[i])
    }
    fmt.Println("الiterate حرفاً بحرف (يتعامل بشكل صحيح مع CJK):")
    for i, r := range s {
        fmt.Printf("  [%d] U+%04X '%c'\n", i, r, r)
    }
}
▶ جرّب الكود

المخرجات:

TEXT
دور المستخدم: مشرف (القيمة: 2)

قيمة صلاحيات المستخدم: 3 (ثنائي: 011)
هل لديه صلاحية القراءة؟ true
هل لديه صلاحية التنفيذ؟ false

درجة حرارة الجسم: 36.6°م → الجزء الصحيح: 36
العدد 65 → الحرف: A، النص: "65"

النص "Hello,عالم" الطول: 14 بايت
الiterate بايت ببايت (غير مُوصى به لـ CJK):
  [0] 72 H
  [1] 101 e
  [2] 108 l
  [3] 108 l
  [4] 111 o
  [5] 44 ,
  [6] 228 ?
  [7] 184 ?
  [8] 150 ?
  [9] 228 ?
  [10] 150 ?
  [11] 175 ?
الiterate حرفاً بحرف (يتعامل بشكل صحيح مع CJK):
  [0] U+0048 'H'
  [1] U+0065 'e'
  [2] U+006C 'l'
  [3] U+006C 'l'
  [4] U+006F 'o'
  [5] U+002C ','
  [6] U+0639 'ع'
  [7] U+0627 'ا'

النقاط الرئيسية:


مثال 3: التطبيق الشامل (الصعوبة ⭐⭐⭐)

السيناريو: محاكاة نظام بسيط لمعالجة معلومات تسجيل المستخدمين، يجمع بين المتغيرات والثوابت والتحويل بين الأنواع والإخراج المنسق.

GO
package main

import (
	"fmt"
	"strings"
)

// ========== الثوابت ==========

// تعداد الجنس
type Gender int

const (
	Unknown Gender = iota // 0: غير معروف
	Male                  // 1: ذكر
	Female                // 2: أنثى
)

func (g Gender) String() string {
	return [...]string{"غير معروف", "ذكر", "أنثى"}[g]
}

// مستويات العضوية والخصومات المقابلة
const (
	LevelBronze   = 1
	LevelSilver   = 2
	LevelGold     = 3
	LevelPlatinum = 4
)

// استخدام iota لتوليد نسب الخصم
const (
	_                   = iota // تخطي 0
	DiscountBronze   = 95      // خصم 5%
	DiscountSilver   = 90      // خصم 10%
	DiscountGold     = 85      // خصم 15%
	DiscountPlatinum = 80      // خصم 20%
)

// ========== هيكل المستخدم (معاينة، يُشرح بالتفصيل في دروس لاحقة) ==========

type User struct {
	Name     string
	Age      int
	Gender   Gender
	Level    int
	Balance  float64
}

// ========== المنطق الأساسي ==========

func main() {
	// بيانات مستخدمين محاكاة
	users := []User{
		{Name: "Li Ming", Age: 25, Gender: Male, Level: LevelGold, Balance: 1580.50},
		{Name: "Wang Fang", Age: 30, Gender: Female, Level: LevelPlatinum, Balance: 3200.00},
		{Name: "Zhang Wei", Age: 17, Gender: Male, Level: LevelBronze, Balance: 200.00},
		{Name: "Zhao Min", Age: 22, Gender: Female, Level: LevelSilver, Balance: 800.75},
	}

	fmt.Println("╔══════════════════════════════════════════════════════════╗")
	fmt.Println("║              نظام تسجيل المستخدمين                     ║")
	fmt.Println("╚══════════════════════════════════════════════════════════╝")
	fmt.Println()

	// متغيرات الإحصائيات
	var totalAge int
	var totalBalance float64
	var maleCount, femaleCount int
	var adultCount int

	for _, u := range users {
		// الحصول على الخصم
		discount := getDiscount(u.Level)
		discountAmount := u.Balance * float64(100-discount) / 100.0

		// تنسيق إخراج معلومات المستخدم
		ageTag := ""
		if u.Age >= 18 {
			ageTag = "بالغ"
			adultCount++
		} else {
			ageTag = "قاصر"
		}

		fmt.Printf("%-8s | الجنس: %-6s | العمر: %d (%s) | المستوى: Lv.%d | الرصيد: $%.2f\n",
			u.Name, u.Gender, u.Age, ageTag, u.Level, u.Balance)
		fmt.Printf("   خصم %d%%، وفور $%.2f\n", discount, discountAmount)

		// الإحصائيات
		totalAge += u.Age
		totalBalance += u.Balance
		switch u.Gender {
		case Male:
			maleCount++
		case Female:
			femaleCount++
		}

		fmt.Println(strings.Repeat("-", 60))
	}

	// طباعة الإحصائيات
	avgAge := float64(totalAge) / float64(len(users))
	fmt.Println()
	fmt.Println("الإحصائيات:")
	fmt.Printf("   إجمالي المستخدمين: %d\n", len(users))
	fmt.Printf("   ذكور: %d | إناث: %d\n", maleCount, femaleCount)
	fmt.Printf("   بالغون: %d | قاصرون: %d\n", adultCount, len(users)-adultCount)
	fmt.Printf("   متوسط العمر: %.1f سنة\n", avgAge)
	fmt.Printf("   إجمالي الرصيد: $%.2f\n", totalBalance)
	fmt.Printf("   متوسط الرصيد: $%.2f\n", totalBalance/float64(len(users)))

	// عرض تحويل الأنواع والتنسيق
	fmt.Println()
	fmt.Println("عرض تحويل الأنواع:")
	demoTypeConversion()
}

// getDiscount يُعيد الخصم بناءً على مستوى العضوية
func getDiscount(level int) int {
	switch level {
	case LevelBronze:
		return DiscountBronze
	case LevelSilver:
		return DiscountSilver
	case LevelGold:
		return DiscountGold
	case LevelPlatinum:
		return DiscountPlatinum
	default:
		return 100 // بدون خصم
	}
}

// demoTypeConversion يعرض سيناريوهات مختلفة للتحويل بين الأنواع
func demoTypeConversion() {
	// 1. تحويل الأنواع العددية
	var pi float64 = 3.14159
	var intPi int = int(pi) // يقطع، لا يُقرب
	fmt.Printf("   float64 → int: %.5f → %d\n", pi, intPi)

	// 2. عدد → نص (مقارنة طريقتين)
	var num int = 2024
	way1 := string(rune(num))      // حرف Unicode → ليس ما تريده
	way2 := fmt.Sprintf("%d", num) // نص عشري → "2024"
	way3 := fmt.Sprintf("%x", num) // نص ست عشري → "7e8"
	fmt.Printf("   int → string (rune):  %q\n", way1)
	fmt.Printf("   int → string (%%d):    %q\n", way2)
	fmt.Printf("   int → string (%%x):    %q\n", way3)

	// 3. نص → عدد (باستخدام fmt.Sscanf)
	var parsed int
	_, err := fmt.Sscanf("12345", "%d", &parsed)
	if err == nil {
		fmt.Printf("   string → int (Sscanf): %d\n", parsed)
	}

	// 4. bool → string
	b := true
	boolStr := fmt.Sprintf("%t", b)
	fmt.Printf("   bool → string: %t → %q\n", b, boolStr)

	// 5. الفرق بين rune و byte
	var r rune = 'ع'
	var b2 byte = 'A'
	fmt.Printf("   rune 'ع': القيمة=%d، سداسي=%U، %d بايت (UTF-8)\n", r, r, len(string(r)))
	fmt.Printf("   byte 'A': القيمة=%d، سداسي=%U، 1 بايت\n", b2, b2)
}
▶ جرّب الكود

المخرجات:

TEXT
╔══════════════════════════════════════════════════════════╗
║              نظام تسجيل المستخدمين                     ║
╚══════════════════════════════════════════════════════════╝

Li Ming   | الجنس: ذكر    | العمر: 25 (بالغ) | المستوى: Lv.3 | الرصيد: $1580.50
   خصم 15%، وفور $237.08
------------------------------------------------------------
Wang Fang | الجنس: أنثى   | العمر: 30 (بالغ) | المستوى: Lv.4 | الرصيد: $3200.00
   خصم 20%، وفور $640.00
------------------------------------------------------------
Zhang Wei | الجنس: ذكر    | العمر: 17 (قاصر) | المستوى: Lv.1 | الرصيد: $200.00
   خصم 5%، وفور $10.00
------------------------------------------------------------
Zhao Min  | الجنس: أنثى   | العمر: 22 (بالغ) | المستوى: Lv.2 | الرصيد: $800.75
   خصم 10%، وفور $80.08
------------------------------------------------------------

الإحصائيات:
   إجمالي المستخدمين: 4
   ذكور: 2 | إناث: 2
   بالغون: 3 | قاصرون: 1
   متوسط العمر: 23.5 سنة
   إجمالي الرصيد: $5781.25
   متوسط الرصيد: $1445.31

عرض تحويل الأنواع:
   float64 → int: 3.14159 → 3
   int → string (rune):  "\u07e8"
   int → string (%d):    "2024"
   int → string (%x):    "7e8"
   string → int (Sscanf): 12345
   bool → string: true → "true"
   rune 'ع': القيمة=1593، سداسي=U+0639، 2 بايت (UTF-8)
   byte 'A': القيمة=65، سداسي=U+0041، 1 بايت

النقاط الرئيسية:


3. حالات استخدام شائعة

الحالة 1: إدارة التكوين

GO
package main

import "fmt"

// ثوابت تكوين التطبيق (تتحدد وقت الترجمة، غير قابلة للتغيير)
const (
	AppName    = "GoWeb"
	Version    = "1.0.0"
	MaxRetries = 3
	DefaultTimeout = 30 // ثانية
)

// تعداد البيئات
type Env int

const (
	Dev  Env = iota // تطوير
	Staging         // اختبار
	Prod            // إنتاج
)

func (e Env) String() string {
	return [...]string{"تطوير", "اختبار", "إنتاج"}[e]
}

func main() {
	// متغيرات وقت التشغيل
	currentEnv := Prod
	dbHost := "192.168.1.100"
	dbPort := 3306
	debug := currentEnv == Dev

	fmt.Printf("التطبيق: %s v%s\n", AppName, Version)
	fmt.Printf("البيئة: %s\n", currentEnv)
	fmt.Printf("قاعدة البيانات: %s:%d\n", dbHost, dbPort)
	fmt.Printf("وضع التصحيح: %t\n", debug)
	fmt.Printf("المحاولات القصوى: %d، المهلة: %d ثانية\n", MaxRetries, DefaultTimeout)
}

الحالة 2: تنسيق البيانات والتقارير

GO
package main

import "fmt"

func main() {
	// بيانات درجات طلاب محاكاة
	type Student struct {
		Name  string
		Score float64
		Grade string
	}

	students := []Student{
		{"Alice", 92.5, ""},
		{"Bob", 87.0, ""},
		{"Charlie", 76.5, ""},
		{"Diana", 95.0, ""},
		{"Eve", 63.0, ""},
	}

	// تعيين الدرجات تلقائياً بناءً على الدرجات
	for i := range students {
		switch {
		case students[i].Score >= 90:
			students[i].Grade = "A (ممتاز)"
		case students[i].Score >= 80:
			students[i].Grade = "B (جيد)"
		case students[i].Score >= 70:
			students[i].Grade = "C (متوسط)"
		case students[i].Score >= 60:
			students[i].Grade = "D (ناجح)"
		default:
			students[i].Grade = "F (راسب)"
		}
	}

	// طباعة تقرير الدرجات
	fmt.Println("┌─────────┬────────┬────────────┐")
	fmt.Println("│  الاسم  │ الدرجة│   التقدير  │")
	fmt.Println("├─────────┼────────┼────────────┤")
	var total float64
	for _, s := range students {
		fmt.Printf("│ %-7s │ %6.1f │ %-10s │\n", s.Name, s.Score, s.Grade)
		total += s.Score
	}
	fmt.Println("├─────────┼────────┼────────────┤")
	fmt.Printf("│ المتوسط │ %6.1f │            │\n", total/float64(len(students)))
	fmt.Println("└─────────┴────────┴────────────┘")
}

❓ أسئلة شائعة

س1: أيهما أستخدم، var أم :=؟ (ارتباك مفاهيمي)

ج: اتبع هذا المبدأ البسيط:

السيناريو المُوصى به السبب
إعلان وإسناد داخل الدالة := أكثر اختصاراً، اتفاقية مجتمع Go
إعلان بدون إسناد داخل الدالة var := تتطلب إسناداً
متغير على مستوى الحزمة var := لا يمكن استخدامها خارج الدوال
تحديد نوع صريح var تجنب استنتاج نوع غير متوقع
GO
func example() {
    // مُوصى به: استخدم := داخل الدوال
    name := "Go"
    count := 0

    // يجب استخدام var: إعلان بدون إسناد
    var result string
    if someCondition {
        result = "yes"
    } else {
        result = "no"
    }

    // يجب استخدام var: نوع دقيق مطلوب
    var b byte = 255 // := ستستنتج كـ int
}

س2: لماذا string(65) لا يساوي "65"؟ (مصيدة شائعة)

ج: string(int) تعامل العدد كـ نقطة كود Unicode، وليس كتمثيل نصي للعدد:

GO
// افتراض خاطئ
s1 := string(65) // المتوقع "65"، فعلياً "A" (Unicode U+0041)

// النهج الصحيح
s2 := fmt.Sprintf("%d", 65)  // "65"
s3 := strconv.Itoa(65)       // "65" (يتطلب import "strconv")

// الاستخدام الحقيقي لـ string(rune): نقطة كود Unicode → حرف
ch := string(rune(1593)) // "ع" (U+0639)

س3: لماذا len("Hello,عالم") لا يساوي 8؟ (مصيدة شائعة)

ج: len() يُعيد عدد البايتات، وليس عدد الأحرف. نصوص Go تستخدم ترميز UTF-8 افتراضياً، والأحرف العربية تشغل 2 بايتات لكل حرف:

GO
s := "Hello,عالم"
fmt.Println(len(s))          // 14 (6 + 4×2 = 14 بايت)
fmt.Println(utf8.RuneCountInString(s)) // 10 (6 + 4 = 10 أحرف)

// الطريقة الصحيحة لعد الأحرف
count := 0
for range s {
    count++
}
fmt.Println(count) // 10

س4: كيف أُبدّل متغيرين بسرعة؟ (نصية عملية)

ج: Go يدعم الإسناد المتعدد، سطر واحد من الكود يكفي:

GO
a, b := 10, 20
a, b = b, a // تبديل: a=20, b=10

// يمكنك أيضاً تجاهل قيمة بهذه الطريقة
_, err := someFunction() // استخدم _ لتجاهل قيمة الإرجاع غير المرغوبة

📖 ملخص


📝 تمارين

تمرين 1 (⭐): المتغيرات والقيم الصفرية

أعلن المتغيرات التالية واطبع قيمها الصفرية:

المخرجات المتوقعة:

TEXT
count: 0
price: 0
active: false
message: ""

تمرين 2 (⭐⭐): تعداد iota والتحويل بين الأنواع

عرّف نوع Color (أساسي int)، واستخدم iota لتعريف ثلاثة ألوان: Red=0، Green=1، Blue=2. نفّذ طريقة String() لـ Color. ثم:

  1. أعلن متغير Color مضبوطاً على Green، واطبع اسمه وقيمته.
  2. حوّل قيمة float64 المقدار 3.14159 إلى int، واطبع النتيجة (يجب أن تكون 3).
  3. حوّل العدد 2025 إلى النص "2025"، واطبع النتيجة.

تمرين 3 (⭐⭐⭐): أداة تحويل درجات الحرارة

اكتب برنامجاً يقوم بما يلي:

  1. يعرّف ثابت AbsoluteZeroC = -273.15 (الصفر المطلق بالدرجة المئوية).
  2. يعلن مجموعة درجات حرارة مئوية: -40, 0, 37, 100.
  3. يiterate على مصفوفة درجات الحرارة، ويُحوّل كل درجة مئوية إلى فهرنهايت (المعادلة: F = C × 9/5 + 32).
  4. يُنسّق المخرجات كجدول، بالمتطلبات:
    • درجات الحرارة المئوية والفهرنهايت مُقربة إلى خانة عشرية واحدة
    • ملاحظة ما إذا كانت درجة الحرارة أقل من الصفر المطلق (مستحيل فيزيائياً)
    • محاذاة عرض الأعمدة

المخرجات المتوقعة:

TEXT
┌─────────┬─────────┬────────────┐
│ مئوية  │فهرنهايت│   الحالة   │
├─────────┼─────────┼────────────┤
│  -40.0  │  -40.0  │ صالح      │
│    0.0  │   32.0  │ صالح      │
│   37.0  │   98.6  │ صالح      │
│  100.0  │  212.0  │ صالح      │
└─────────┴─────────┴────────────┘

تلميح: استخدم const، var (مصفوفة/slice)، حلقة for، تنسيق fmt.Printf، تحويل الأنواع (intfloat64).


الدرس التالي

الدرس 3: تدفق التحكم — if/else، switch، حلقات for

Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%