Learn in 10 minutes

Learn in 10 minutes

تعلم لغة Go في 10 دقائق

Go (المعروفة أيضًا باسم Golang) هي لغة برمجة مترجمة وثابتة النوع تم تصميمها في Google. تشتهر ببساطتها وكفاءتها ودعمها الممتاز للتزامن. سيساعدك هذا البرنامج التعليمي على تعلم برمجة Go بسرعة.

1. كتابة أول برنامج Go

لنبدأ ببرنامج بسيط. أنشئ ملفًا باسم hello.go وأدخل الكود التالي:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

احفظ الملف وقم بتشغيل الأمر التالي في الطرفية:

go run hello.go

سيكون الناتج:

Hello, World!

يوضح هذا البرنامج البسيط الهيكل الأساسي لـ Go:

  • package main يعلن اسم الحزمة
  • import "fmt" يستورد حزمة التنسيق لعمليات الإدخال/الإخراج
  • func main() هي نقطة الدخول للبرنامج
  • fmt.Println() يطبع النص إلى وحدة التحكم

2. التركيب الأساسي

تمتلك Go تركيبًا نظيفًا وبسيطًا. على عكس Python، تستخدم Go الأقواس المعقوفة {} لتحديد كتل الكود وتتطلب فواصل منقوطة في نهاية العبارات (على الرغم من إدخالها تلقائيًا عادةً).

// هذا تعليق من سطر واحد
fmt.Println("Hello, World!")

/*
هذا تعليق متعدد الأسطر
يمتد عبر عدة أسطر
*/

قواعد التركيب الأساسية في Go:

  • كتل الكود: تُحدد بواسطة الأقواس المعقوفة {}
  • التعليقات: التعليقات أحادية السطر تبدأ بـ //، والتعليقات متعددة الأسطر بـ /* */
  • العبارات: تنتهي بفواصل منقوطة (تُدخل تلقائيًا)
  • إعلان الحزمة: يبدأ كل ملف بإعلان حزمة

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

Go هي لغة ثابتة النوع، مما يعني أنه يجب عليك الإعلان عن أنواع المتغيرات. ومع ذلك، تدعم Go الاستدلال على النوع باستخدام عامل التشغيل :=.

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

// إعلان نوع صريح
var name string = "John"
var age int = 25

// الاستدلال على النوع
name := "John"
age := 25

// إعلان متغيرات متعددة
var x, y int = 10, 20
x, y := 10, 20

أنواع البيانات الأساسية الرئيسية في Go:

  • أنواع الأعداد الصحيحة: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr
  • أنواع الأعداد العشرية: float32, float64
  • النصوص: string
  • المنطقية: bool
  • أنواع الأعداد المركبة: complex64, complex128

3.1 الأنواع الرقمية

توفر Go أنواعًا رقمية متنوعة لاستخدامات مختلفة:

// أنواع الأعداد الصحيحة
var age int = 25
var smallNumber int8 = 127
var largeNumber int64 = 9223372036854775807

// أنواع الأعداد العشرية
var temperature float32 = 36.5
var pi float64 = 3.14159265359

// الأعداد المركبة
var complexNum complex64 = 3 + 4i

3.2 نوع النصوص

النصوص في Go هي تسلسلات من البايتات وهي غير قابلة للتغيير:

// إعلان النصوص
var greeting string = "Hello, Go!"
name := "Alice"

// عمليات النصوص
fmt.Println(len(greeting))        // طول النص
fmt.Println(greeting[0])          // الوصول إلى الحرف الأول (بايت)
fmt.Println(greeting[0:5])        // تقطيع النص
fmt.Println(strings.ToUpper(name)) // التحويل إلى أحرف كبيرة

3.3 النوع المنطقي

النوع المنطقي له قيمتان: true و false:

var isActive bool = true
var isComplete bool = false

// العمليات المنطقية
result1 := true && false  // false
result2 := true || false  // true
result3 := !true          // false

4. الثوابت

يتم الإعلان عن الثوابت باستخدام الكلمة المفتاحية const ولا يمكن تغييرها:

const Pi = 3.14159
const MaxUsers = 1000

// ثوابت متعددة
const (
    StatusOK = 200
    StatusNotFound = 404
    StatusError = 500
)

// ثوابت محددة النوع
const Version string = "1.0.0"

5. هياكل البيانات

توفر Go عدة هياكل بيانات مدمجة لتخزين البيانات ومعالجتها.

5.1 المصفوفات

المصفوفات هي تسلسلات ذات حجم ثابت من العناصر من نفس النوع:

// إعلان المصفوفة
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
names := [3]string{"Alice", "Bob", "Charlie"}

// الوصول إلى العناصر
fmt.Println(numbers[0])  // 1
numbers[0] = 10         // تعديل العنصر

// طول المصفوفة
fmt.Println(len(numbers)) // 5

5.2 الشرائح (Slices)

الشرائح هي مصفوفات ديناميكية يمكن أن تنمو وتتقلص:

// إعلان الشريحة
numbers := []int{1, 2, 3, 4, 5}
var emptySlice []int

// إنشاء شرائح من المصفوفات
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4]  // [2, 3, 4]

// عمليات الشرائح
numbers = append(numbers, 6)      // إضافة عنصر
numbers = append(numbers, 7, 8, 9) // إضافة عناصر متعددة

// سعة الشريحة وطولها
fmt.Println(len(numbers)) // الطول: 9
fmt.Println(cap(numbers)) // السعة: 10 (قد تختلف)

5.3 الخرائط (Maps)

الخرائط هي مجموعات غير مرتبة من أزواج المفتاح-القيمة:

// إعلان الخريطة
student := map[string]interface{}{
    "name": "John",
    "age":  20,
    "major": "Computer Science",
}

// إعلان بديل
var scores map[string]int = make(map[string]int)
scores["math"] = 95
scores["science"] = 88

// الوصول والتعديل
fmt.Println(student["name"])
student["age"] = 21
student["gpa"] = 3.8

// وصول آمن
if phone, exists := student["phone"]; exists {
    fmt.Println(phone)
} else {
    fmt.Println("Phone not provided")
}

// التكرار عبر الخريطة
for key, value := range student {
    fmt.Printf("%s: %v\n", key, value)
}

5.4 الهياكل (Structs)

الهياكل هي مجموعات من الحقول التي يمكن أن يكون لها أنواع مختلفة:

// تعريف الهيكل
type Person struct {
    Name string
    Age  int
    City string
}

// إنشاء مثيلات الهيكل
person1 := Person{"Alice", 25, "New York"}
person2 := Person{
    Name: "Bob",
    Age:  30,
    City: "London",
}

// الوصول إلى الحقول
fmt.Println(person1.Name)
person1.Age = 26

6. العمليات وعوامل التشغيل

توفر Go مجموعة غنية من عوامل التشغيل للحسابات والمقارنات المختلفة.

  • عوامل التشغيل الحسابية: +, -, *, /, % (الباقي)
  • عوامل التشغيل المقارنة: ==, !=, >, <, >=, <=
  • عوامل التشغيل المنطقية: &&, ||, !
  • عوامل التشغيل البتية: &, |, ^, <<, >>
  • عوامل التشغيل التعيينية: =, +=, -=, *=, /=

6.1 عوامل التشغيل الحسابية

a, b := 10, 3

fmt.Printf("Addition: %d\n", a + b)      // 13
fmt.Printf("Subtraction: %d\n", a - b)   // 7
fmt.Printf("Multiplication: %d\n", a * b)  // 30
fmt.Printf("Division: %d\n", a / b)      // 3
fmt.Printf("Modulus: %d\n", a % b)      // 1

6.2 عوامل التشغيل المقارنة

x, y := 5, 10

fmt.Printf("Equal: %t\n", x == y)     // false
fmt.Printf("Not equal: %t\n", x != y) // true
fmt.Printf("Greater than: %t\n", x > y)  // false
fmt.Printf("Less than: %t\n", x < y)  // true

6.3 عوامل التشغيل المنطقية

a, b := true, false

fmt.Printf("AND operation: %t\n", a && b)  // false
fmt.Printf("OR operation: %t\n", a || b)    // true
fmt.Printf("NOT operation: %t\n", !a)    // false

7. التحكم في التدفق

توفر Go عدة عبارات للتحكم في تدفق البرنامج.

7.1 عبارات if

age := 20
if age >= 18 {
    fmt.Println("Adult")
} else if age >= 13 {
    fmt.Println("Teen")
} else {
    fmt.Println("Child")
}

// if مع عبارة قصيرة
if score := 85; score >= 90 {
    fmt.Println("Grade: A")
} else if score >= 80 {
    fmt.Println("Grade: B")
} else {
    fmt.Println("Grade: C")
}

7.2 حلقات for

تمتلك Go بناءً واحدًا فقط للحلقات: for

// حلقة for أساسية
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// حلقة على نمط while
count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

// حلقة لا نهائية
for {
    fmt.Println("This will run forever")
    break // استخدم break للخروج
}

// حلقة range (للشرائح، المصفوفات، الخرائط)
fruits := []string{"apple", "banana", "cherry"}
for index, fruit := range fruits {
    fmt.Printf("%d: %s\n", index, fruit)
}

7.3 عبارات switch

day := "Monday"
switch day {
case "Monday":
    fmt.Println("Start of the week")
case "Friday":
    fmt.Println("Weekend is near")
case "Saturday", "Sunday":
    fmt.Println("Weekend!")
default:
    fmt.Println("Regular day")
}

// Switch بدون تعبير
score := 85
switch {
case score >= 90:
    fmt.Println("Grade: A")
case score >= 80:
    fmt.Println("Grade: B")
case score >= 70:
    fmt.Println("Grade: C")
default:
    fmt.Println("Grade: F")
}

8. الدوال

الدوال في Go هي مواطن من الدرجة الأولى وتدعم قيم إرجاع متعددة.

8.1 الدوال الأساسية

func greet(name string) string {
    return "Hello, " + name + "!"
}

// استدعاء الدالة
message := greet("John")
fmt.Println(message)

8.2 قيم الإرجاع المتعددة

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("cannot divide by zero")
    }
    return a / b, nil
}

// استخدام قيم الإرجاع المتعددة
result, err := divide(10, 2)
if err != nil {
    fmt.Println("Error:", err)
} else {
    fmt.Println("Result:", result)
}

8.3 قيم الإرجاع المسماة

func calculateRectangle(width, height float64) (area float64, perimeter float64) {
    area = width * height
    perimeter = 2 * (width + height)
    return // إرجاع عاري
}

area, perimeter := calculateRectangle(5, 3)
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", area, perimeter)

8.4 الدوال المتغيرة

func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

fmt.Println(sum(1, 2, 3, 4))  // 10
fmt.Println(sum(5, 10, 15))   // 30

9. المؤشرات

تمتلك Go مؤشرات ولكن بتركيب أبسط من C/C++:

func modifyValue(x *int) {
    *x = *x * 2
}

func main() {
    value := 10
    fmt.Println("Before:", value) // 10

    modifyValue(&value)
    fmt.Println("After:", value)  // 20
}

10. الطرق

الطرق هي دوال ذات وسيط مستقبل:

type Rectangle struct {
    Width  float64
    Height float64
}

// طريقة بمستقبل قيمة
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// طريقة بمستقبل مؤشر
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

rect := Rectangle{Width: 5, Height: 3}
fmt.Println("Area:", rect.Area()) // 15

rect.Scale(2)
fmt.Println("Scaled Area:", rect.Area()) // 60

11. الواجهات

تحدد الواجهات تواقيع الطرق التي يمكن للأنواع تنفيذها:

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * 3.14159 * c.Radius
}

func printShapeInfo(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

circle := Circle{Radius: 5}
printShapeInfo(circle)

12. معالجة الأخطاء

تستخدم Go معالجة الأخطاء الصريحة بدلاً من الاستثناءات:

func readFile(filename string) (string, error) {
    data, err := os.ReadFile(filename)
    if err != nil {
        return "", fmt.Errorf("failed to read file %s: %w", filename, err)
    }
    return string(data), nil
}

content, err := readFile("example.txt")
if err != nil {
    fmt.Println("Error:", err)
    return
}
fmt.Println("Content:", content)

13. التزامن مع Goroutines

Goroutines هي خيوط خفيفة الوزن تديرها بيئة تشغيل Go:

func worker(id int) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Worker %d: %d\n", id, i)
        time.Sleep(time.Millisecond * 100)
    }
}

func main() {
    // بدء عدة goroutines
    for i := 1; i <= 3; i++ {
        go worker(i)
    }

    // الانتظار حتى تكتمل goroutines
    time.Sleep(time.Second)
    fmt.Println("All workers completed")
}

14. القنوات

تُستخدم القنوات للتواصل بين goroutines:

func producer(ch chan<- int) {
    for i := 0; i < 5; i++ {
        ch <- i // إرسال قيمة إلى القناة
        time.Sleep(time.Millisecond * 100)
    }
    close(ch) // إغلاق القناة عند الانتهاء
}

func consumer(ch <-chan int) {
    for value := range ch {
        fmt.Println("Received:", value)
    }
}

func main() {
    ch := make(chan int, 3) // قناة مخزنة

    go producer(ch)
    consumer(ch)

    fmt.Println("Channel communication completed")
}

15. عمليات الملفات

توفر Go طرقًا بسيطة لقراءة الملفات وكتابتها:

// قراءة الملفات
data, err := os.ReadFile("example.txt")
if err != nil {
    fmt.Println("Error reading file:", err)
    return
}
fmt.Println("File content:", string(data))

// كتابة الملفات
content := "Hello, Go!\n"
err = os.WriteFile("output.txt", []byte(content), 0644)
if err != nil {
    fmt.Println("Error writing file:", err)
    return
}
fmt.Println("File written successfully")

16. الحزم والوحدات

تدير وحدات Go التبعيات وإصدارات الحزم:

// استيراد حزم المكتبة القياسية
import (
    "fmt"
    "math"
    "strings"
)

func main() {
    fmt.Println(math.Sqrt(16))        // 4
    fmt.Println(strings.ToUpper("go")) // GO
}

لإنشاء حزمة خاصة بك، أنشئ دليلًا باسم حزمتك وقم بتصدير الدوال عن طريق كتابة أسمائها بأحرف كبيرة.

17. الاختبار

تمتلك Go دعمًا مدمجًا للاختبار:

// في ملف math_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    result := add(2, 3)
    expected := 5
    if result != expected {
        t.Errorf("add(2, 3) = %d; want %d", result, expected)
    }
}

func add(a, b int) int {
    return a + b
}

شغل الاختبارات باستخدام: go test

18. أفضل الممارسات

  • استخدم gofmt لتنسيق الكود الخاص بك
  • اتبع اصطلاحات تسمية Go (camelCase للمتغيرات، PascalCase للتصدير)
  • عالج الأخطاء بشكل صريح
  • استخدم الواجهات للتجريد
  • فضل التركيب على الوراثة
  • اكتب اختبارات شاملة
  • استخدم المكتبة القياسية كلما أمكن

يغطي هذا البرنامج التعليمي الميزات الأساسية لبرمجة Go. مع الممارسة، ستتمكن من بناء تطبيقات فعالة ومتزامنة باستخدام الميزات القوية لـ Go.