إنشاء الحزم في لغة جو Go


إنشاء الحزم في لغة جو Go February 28, 2023 at 07:06PM

تُعَدّ الحزمة مجموعةً من الملفات الموجودة ضمن مجلد واحد والمتضمّنة لتعليمة الحزمة نفسها في بدايتها، ويمكنك تضمين العديد من الحزم ضمن برنامجك عند الحاجة لبناء برمجيات أكثر تعقيدًا.

تكون بعض الحزم موجودةً في مكتبة جو القياسية وبعضها الآخر يمكنك تثبيته من خلال الأمر go get، كما يمكنك أيضًا إنشاء الحزم الخاصة بك من خلال بناء ملفات لغة جو التي تحتاجها ووضعه ضمن المجلد نفسه مع الالتزام بكتابة تعليمة الحزمة الضرورية في بداية كل ملف، كما ستتعلم في هذا المقال كيفية إنشاء حزم لغة جو الخاصة بك لاستخدامها في برامجك.

المتطلبات

كتابة واستيراد الحزم

تشبه كتابة الحزم كتابة أيّ برنامج آخر في لغة جو، ويمكن أن تتضمن الحزم دوالًا أو متغيرات أو أنواع بيانات خاصة يمكنك استخدامها في برنامجك لاحقًا.

يجب أن تكون ضمن مساحة العمل الخاصة بك قبل إنشاء حزم جديدة، وهذا يعني أن تكون ضمن مسار البيئة gopath، ففي هذا المقال مثلًا سنُنشئ الحزمة greet، لذا سنُنشئ المجلد greet ضمن مسار البيئة وضمن مساحة العمل الخاصة بك، فإذا كنا ضمن مساحة العمل gopherguides وأردنا إنشاء الحزمة greet ضمنها أثناء استخدام جيت هاب Github على أساس مستودع تعليمات برمجية، فسيبدو المجلد كما يلي:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides

ستكون الحزمة greet ضمن المجلد gopherguides:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet

يمكننا الآن إنشاء أول ملف في الحزمة، ويسمى الملف الأساسي -ويسمى أيضًا نقطة الدخول entry point- في الحزمة عادةً باسم الحزمة نفسها، إذًا سنُنشئ الملف greet.go ضمن المجلد greet كما يلي:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet
                    └── greet.go

يمكننا بعد إنشاء الملف كتابة التعليمات البرمجية التي نريدها ضمنه، ويكون الهدف من هذه التعليمات عادةً هو الاستخدام في مكان آخر من المشروع، وفي هذه الحالة سننشئ دالة Hello تطبع Hello World، لذا افتح الملف greet.go من خلال محرر الشيفرات الخاص بك واكتب ضمنه التعليمات التالية:

package greet

import "fmt"

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

يجب دومًا أن نبدأ باسم الحزمة التي نعمل ضمنها لكي نُخبر المصرِّف أنّ هذا الملف هو جزء من الحزمة، لذا كتبنا الكلمة المفتاحية package متبوعةً باسم الحزمة:

package greet

ثم نكتب اسم الحزم التي نحتاج إلى استخدامها ضمن الملف من خلال وضع أسمائها بعد الكلمة المفتاحية import، وهنا نحتاج إلى حزمة fmt فقط:

import "fmt"

أخيرًا سنكتب الدالة Hello التي تستخدِم الحزمة fmt لتنسيق طباعة جملة الخرج:

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

نكون الآن قد انتهينا من إنشاء الملف الأول وأصبح بإمكاننا استخدام الدالة Hello منه وفي المكان الذي نريده.

سنُنشئ الآن حزمةً جديدةً سنسميها example، لذا يجب أن نُنشئ مجلدًا لها بالاسم نفسه، وسننشئه ضمن مساحة العمل نفسها gopherguides:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                    └── example

الآن وقد أصبح لديك مجلدًا خاصًا بالحزمة، بات بإمكانك إنشاء ملف نقطة الدخول، والذي سيكون ملفًا رئيسيًا -أي ملف تنفيذي-، لذا سنسميه main.go:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── example
                    └── main.go

افتح الملف من محرر الشيفرات الخاص بك واكتب التعليمات التالية:

package main

import "github.com/gopherguides/greet"

func main() {
    greet.Hello()
}

بما أن الدالة التي تريد استخدامها ضمن الملف الرئيسي موجودة ضمن حزمة أخرى، فسيتوجب عليك استدعاؤها من خلال ذكر اسم الحزمة أولًا متبوعًا بنقطة ثم اسم الدالة، فمثلًا وضعنا هنا اسم الحزمة greet ثم نقطة ثم اسم الدالة ()greet.Hello، ويمكنك الآن فتح الطرفية وتشغيل البرنامج ضمنها:

go run main.go

سيكون الخرج كما يلي:

Hello, World!

سنضيف بعض المتغيرات إلى ملف greet.go لتتعلم كيفية استخدام المتغيرات ضمن الحزمة:

package greet

import "fmt"

var Shark = "Sammy"

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

ثم افتح الملف main.go وأضف التعليمة التالية (fmt.Println(greet.Shark لاستدعاء المتغير Shark داخل الدالة fmt.Println، أي كما يلي:

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)
}

ثم شغّل الشيفرة مرةً أخرى:

$ go run main.go

ستحصل على الخرج التالي:

Hello, World!
Sammy

أخيرًا، سننشئ نوع بيانات جديد ضمن ملف greet.go، إذ سننشئ نوع البيانات Octopus الذي يتضمّن الحقلين name و color، كما سنعرّف دالةً تطبع هذه الحقول:

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

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

سننشئ الآن نسخةً من هذا النوع داخل الملف main.go:

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())
}

بمجرّد إنشاء نسخة من النوع Octopus عند كتابة oct := greet.Octopus يُصبح بإمكاننا الوصول إلى الداول والمتغيرات الموجودة ضمنه من الملف main، وبالتالي إمكانية استدعاء الدالة ()oct.String من دون الحاجة لكتابة اسم الحزمة greet، كما يمكنك الوصول إلى الحقول بالطريقة نفسها دون الحاجة إلى كتابة اسم الحزمة مثل oct.Color.

يستخدِم التابع String التي يتضمنها النوع Octopus الدالة fmt.Sprintf لإنشاء وإرجاع سلسلة في المكان الذي استُدعي فيه أي في هذه الحالة في الملف main، وسنشغّل البرنامج الآن كما يلي:

$ go run main.go

يكون الخرج كما يلي:

Hello, World!
Sammy
The octopus's name is "Jesse" and is the color orange.

إذًا سيصبح لدينا دالة يمكن استخدامها حيثما نريد لطباعة معلومات عن نوع البيانات الذي عرّفناه من خلال تعريفنا للتابع String ضمن النوع Octopus، فإذا أردت تغيير سلوك هذا التابع لاحقًا، فيمكنك ببساطة تعديله فقط حيثما يكون.

تصدير الشيفرة

لاحظ أنّ كل التصريحات داخل الملف greet.go تبدأ بمحرف كبير، ولا تمتلك لغة جو مفاهيم مُحددات الوصول العامة public والخاصة private والمحمية protected كما في باقي اللغات، ويمكن التحكم بالرؤية في لغة جو من خلال الكتابة بمحارف كبيرة، فالمتغيرات أو الدوال أو الأنواع التي تبدأ بمحارف كبيرة تكون مرئيةً من خارج الحزمة -أي عامة- ويُعتبر عندها مُصدّرًا exported.

إذا أضفت تابعًا جديدًا إلى النوع Octopus اسمه reset، فستتمكّن من استدعائه من داخل الحزمة greet، لكن لن تتمكن من استدعائه من الملف main.go لأنه خارج الحزمة greet:

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) reset() {
    o.Name = ""
    o.Color = ""
}

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

إذا حاولت استدعاء reset من الملف main.go:

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.reset()
}

ستحصل على الخطأ التالي والذي يقول أنه لا يمكن الإشارة إلى حقل أو دالة غير مصدرة:

oct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset)

لتصدير دالة reset من Octopus، اجعل المحرف الأول من الدالة كبيرًا، أي Reset:

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) Reset() {
    o.Name = ""
    o.Color = ""
}

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

وبالتالي سيصبح بإمكانك استدعائها من الحزمة الأخرى بدون مشاكل:

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.Reset()

    fmt.Println(oct.String())
}

الآن إذا شغّلت البرنامج:

$ go run main.go

ستتلقى الخرج التالي:

Hello, World!
Sammy
The octopus's name is "Jesse" and is the color orange
The octopus's name is "" and is the color .

نلاحظ من خلال استدعاء الدالة Reset أن جميع بيانات الحقول Name و Color قد مسحتها، وعند استدعاء التابع String لاتطبع شيئًا لأن الحقول السابقة قد أصبحت فارغةً.

الخاتمة

تشبه كتابة الحزم في لغة جو كتابة أيّ ملف في لغة جو، إلا أن وضعها في مجلد مُختلف سيسمح لك بعزل الشيفرة لإعادة استخدامها في مكان آخر، وقد تحدثنا في هذا المقال عن كيفية تعريف وإنشاء الحزم وكيفية الاستفادة منها في ملفات أخرى وأين يمكن وضعها للوصول إليها.

ترجمة -وبتصرُّف- للمقال How To Write Packages in Go لصاحبه Gopher Guides.

اقرأ أيضًا

#oqpahameedq

تعليقات