Skip to content

ورقة غش لغة البرمجة Go

Go (تُعرف أيضاً باسم Golang) هي لغة مجمعة وذات كتابة ثابتة تم تطويرها بواسطة Robert Griesemer و Rob Pike و Ken Thompson في Google. تشبه قواعد Go قواعد لغة C، ولكنها تتميز بـ: سلامة الذاكرة، و GC (جمع النفايات)، والنوع الهيكلي، وحساب التزامن بنمط CSP.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

المتغيرات

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

var msg string
msg = "Hello"

الاختصار

msg := "Hello"

الثوابت

const Phi = 1.618

يمكن أن تكون الثوابت أحرفاً أو سلاسل نصية أو قيماً منطقية أو قيمًا رقمية.

الأنواع الأساسية

السلاسل النصية (Strings)

str := "Hello"
str := `سلسلة
متعددة الأسطر`

نوع السلاسل النصية هو string.

الأرقام

الأنواع النموذجية

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (اسم مستعار لـ uint8)

أنواع أخرى

var u uint = 7        // uint (بدون إشارة)
var p float32 = 22.7  // float 32-bit

المؤشرات (Pointers)

func main () {
  b := *getPointer()
  fmt.Println("القيمة هي", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

تشير المؤشرات إلى موقع ذاكرة لمتغير. لغة Go مجهزة بالكامل بجمع النفايات (Garbage Collection).

المصفوفات (Arrays)

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

حجم المصفوفات ثابت.

الشرائح (Slices)

slice := []int{2, 3, 4}
slice := []byte("Hello")

على عكس المصفوفات، تتميز الشرائح بحجم ديناميكي.

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

الشروط

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

تعبير في if

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

يمكن لعبارة if تنفيذ عبارة بسيطة قبل التعبير الشرطي.

Switch

switch day {
  case "sunday":
    // الحالات لا "تنفذ تباعاً" افتراضياً!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

الدوال

Lambdas

myfunc := func() bool {
  return x > 10000
}

الدوال هي كائنات من الدرجة الأولى.

أنواع إرجاع متعددة

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

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

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

من خلال تسمية قيم الإرجاع في التعريف، فإن return (بدون وسائط) ستعيد المتغيرات بتلك الأسماء.

الحزم (Packages)

التحميل

import "fmt"
import "math/rand"
import (
  "fmt"        // يعطي fmt.Println
  "math/rand"  // يعطي rand.Intn
)

كلاهما متماثل.

الأسماء المستعارة

import r "math/rand"
 
r.Intn()

الأسماء المصدرة

func Hello () {
  ···
}

تبدأ الأسماء المصدرة بحرف كبير.

الحزم

package hello

يجب أن يبدأ كل ملف حزمة بكلمة package.

التزامن (Concurrency)

Goroutines

func main() {
  // قناة "channel"
  ch := make(chan string)

  // بدء إجراءات متزامنة
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // قراءة 3 نتائج
  // (بما أن goroutines متزامنة،
  // فالترتيب غير مضمون!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

القنوات هي كائنات اتصال آمنة للتزامن تُستخدم في goroutines.

القنوات المخزنة (Buffered Channels)

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// خطأ فادح:
// كل الـ goroutines نائمة - طريق مسدود (deadlock)!

تحد القنوات المخزنة من عدد الرسائل التي يمكنها الاحتفاظ بها.

إغلاق القنوات

يغلق القناة

ch <- 1
ch <- 2
ch <- 3
close(ch)

التنقل عبر القناة حتى إغلاقها

for i := range ch {
  ···
}

تعتبر مغلقة إذا كانت ok == false

v, ok := <- ch

التأجيل والذعر (Defer & Panic)

Defer (التأجيل)

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

يؤجل تنفيذ الدالة حتى تعود الدالة المحيطة. يتم تقييم الوسائط على الفور، ولكن لا يتم استدعاء الدالة حتى النهاية.

Defer مع Lambdas

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

تعتبر Lambdas أفضل للكتل المؤجلة.

الهياكل (Structs)

التعريف

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

الثوابت الحرفية

v := Vertex{X: 1, Y: 2}
// يمكن حذف أسماء الحقول
v := Vertex{1, 2}
// Y ضمني
v := Vertex{X: 1}

يمكنك أيضًا تحديد أسماء الحقول.

المؤشرات إلى الهياكل

v := &Vertex{1, 2}
v.X = 2

عندما يكون v مؤشراً، فإن v.X و (*v).X متماثلان.

الأساليب (Methods)

المستقبِل (Receivers)

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

لا توجد أصناف، ولكن يمكنك تعريف دوال على الأنواع باستخدام المستقبلِلات.

مستقبِلات المؤشر

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// يتم تحديث `v`