تخصيص الثنائيات في لغة Go بواسطة العلامات البناء

مقدمة

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

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

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

المقدمات

لتتبع المثال في هذه المقالة، سيحتاجون إلى:

بناء النسخة المجانية

دعونا نبدأ ببناء نسخة التطبيق المجانية، وسيكون الجهة الافتراضية عندما تتم تجميع go build بدون أي تعايير تجميع. بعد ذلك، سنستخدم تعايير التجميع لإضافة الأجزاء الأخرى إلى مبرمجتنا بطريقة تحديدية.

في دارة src، قم بإنشاء مجلد بإسم تطبيقك. ستستخدم هذا التوريتال app:

  1. mkdir app

تحول إلى هذا المجلد:

  1. cd app

من ثم، أنشأ ملف نص جديد في محررك النص المفضل بإسم main.go:

  1. nano main.go

حاليًا، سنحدد النسخة المجانية للتطبيق. أضف إلى main.go التالي المحتويات:

main.go
package main

import "fmt"

var features = []string{
  "Free Feature #1",
  "Free Feature #2",
}

func main() {
  for _, f := range features {
    fmt.Println(">", f)
  }
}

في هذا الملف، أنشأنا برنامج يدeclares مستوي slice يدعى features، الذي يحتوي على قطعتين strings تمثلان الميزات لتطبيقنا المجاني. توجه main() في البرنامج تستخدم دورة for لمجموع range خلال القطعة features ومطبوع جميع الميزات المتوفرة على الشاشة.

احفظ الملف وأخرج منه. الآن بما أن الملف قد تم حفظه، لن نحتاج بعد الآن إلى تعديله لباقي المقال. بدلاً من ذلك، سنستخدم وسائل البناء لتغيير ميزات الثنائيات التي سنقوم ببنائها منها.

ابنِ وقم بتشغيل البرنامج:

  1. go build
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2

لقد طبع البرنامج ميزتنا الثنائيتين المجانية، مكتملًا الإصدار المجاني من تطبيقنا.

حتى الآن، قمت بإنشاء تطبيق يحتوي على مجموعة ميزات أساسية بسيطة. الآن، ستقوم ببناء طريقة لإضافة المزيد من الميزات إلى التطبيق في وقت بناءه.

إضافة الميزات المحترفة مع go build

لقد تجنبنا حتى الآن تحديث main.go، محاكة بيئة إنتاج شائعة تتطلب إضافة الكود بدون تغيير وربما كسر الكود الرئيسي. بما أننا لا نستطيع تعديل ملف main.go، سنحتاج إلى استخدام آلية أخرى لتضخيم المزيد من الميزات إلى قطعة features باستخدام وسائل البناء.

دعنا نخلق ملفًا جديدًا يُدعى pro.go سيستخدم دالة init() لإضافة المزيد من الميزات إلى قطعة features:.

  1. nano pro.go

بمجرد فتح المحرر للملف، أضف السطرات التالية:

pro.go
package main

func init() {
  features = append(features,
    "Pro Feature #1",
    "Pro Feature #2",
  )
}

في هذا الكود، استخدمنا init() لتشغيل الكود قبل دالة main() لتطبيقنا، ثم استخدمنا append() لإضافة ميزات Pro إلى قطعة features. احفظ الملف وأخرج منه.

قم بتجميع وتشغيل التطبيق باستخدام go build:

  1. go build

لأن هناك الآن ملفين في الدليل الحالي لدينا (pro.go و main.go)، سيقوم go build بإنشاء بينري من كلاهما. قم بتنفيذ هذا البينري:

  1. ./app

سيقدم لك ذلك مجموعة الميزات التالية:

Output
> Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

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

إضافة بطاقات البناء

يمكنك الآن استخدام بطاقات البناء لتمييز الإصدار Pro من التطبيق الخاص بك عن الإصدار المجاني.

دعونا نبدأ بمراجعة شكل بطاقة البناء:

// +build اسم_البطاقة

بوضع هذا السطر من الكود كأول سطر في حزمتك وتبديل اسم_العلامة باسم علامة البناء الخاصة بك، ستلصق علامة هذه الحزمة ككود يمكن تضمينه اختياريًا في الثنائي النهائي. دعنا نرى ذلك في العمل باضافة علامة بناء إلى ملف pro.go لتخبر الأمر go build بتجاهله إلا إذا كانت العلامة محددة. افتح الملف في محرر النصوص:

  1. nano pro.go

ثم أضف السطر المبرز التالي:

pro.go
// +build pro

package main

func init() {
  features = append(features,
    "Pro Feature #1",
    "Pro Feature #2",
  )
}

في أعلى ملف pro.go، أضفنا // +build pro ثم سطر فارغ جديد. هذا السطر الفارغ المتبوع مطلوب، وإلا فإن جو يؤوله كتعليق. يجب أن تكون إعلانات علامات البناء أيضًا في أعلى ملف .go. لا شيء، لا حتى التعليقات، يمكن أن يكون فوق علامات البناء.

يخبر الإعلان +build الأمر go build بأن هذا ليس تعليقًا، بل هو علامة بناء. الجزء الثاني هو علامة pro. بإضافة هذه العلامة في أعلى ملف pro.go، سيشمل الأمر go build ملف pro.go فقط عندما تكون العلامة pro موجودة.

قم بترجمة وتشغيل التطبيق مرة أخرى:

  1. go build
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2

لأن ملف pro.go يتطلب وجود علامة pro، يتم تجاهل الملف ويتم ترجمة التطبيق بدونه.

عند تشغيل الأمر go build، يمكننا استخدام العلامة -tags لتضمين الكود اختياريًا في المصدر المرجم بإضافة العلامة نفسها كحجة. دعونا نفعل ذلك لعلامة pro:

  1. go build -tags pro

سينتج هذا على المادة التالية:

Output
> Free Feature #1 > Free Feature #2 > Pro Feature #1 > Pro Feature #2

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

منطق تواجيد التسجيل

عندما يوجد تواجيد متعددة في قطعة برنامج Go، يتم التفاعل بينها بواسطة منطق المعادلة البولية، لإظهار هذا، سنضيف مستوى الشركة لتطبيقنا باستخدام كلاً من التواجيد pro و enterprise،

ولبناء متغيرة للشركة، سيتوجب علينا أن نشمل الميزات الافتراضية، وميزات مستوى الPro ومجموعة جديدة من الميزات للشركة. أولًا، افتح محررًا وأنشئ ملفًا جديدًا، enterprise.go، الذي سيضيف الميزات الجديدة للشركة:

  1. nano enterprise.go

ستبدو محتويات enterprise.go تقريبًا متشابهة للملف pro.go ولكنها ستحتوي على ميزات جديدة. أضف تلك الخطوات التالية إلى الملف:

enterprise.go
package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

أحفظ وخرج من الملف.

الحاليًا، ملف enterprise.go ليس لديه أي بطاقات بناء، وكما تعلمت عندما أضفت pro.go، يعني هذا أن هذه الميزات ستضاف إلى الإصدار المجاني عند تنفيذ go.build. بالنسبة لـ pro.go، أضفت // +build pro وسطر جديد على أعلى الملف لتخبر go build بأنه يجب أن يتم تضمينه فقط عندما يتم استخدام -tags pro. في هذه الحالة، كنت بحاجة إلى بطاقة بناء واحدة فقط لتحقيق الهدف. عند إضافة الميزات الجديدة للشركة، يجب عليك أولاً أن يكون لديك الميزات الPro.

دعونا نضيف دعم بطاقة البناء pro إلى enterprise.go أولاً. افتح الملف باستخدام محرر النصوص الخاص بك:

  1. nano enterprise.go

ثم أضف البطاقة البناء قبل إعلان package main وتأكد من تضمين سطر جديد بعد البطاقة البناء:

enterprise.go
// +build pro

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

احفظ الملف وأغلقه.

قم بترجمة وتشغيل التطبيق بدون أي بطاقات:

  1. go build
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2

الميزات الشركة لم تعد تظهر في الإصدار المجاني. الآن دعونا نضيف بطاقة البناء pro ونقوم بترجمة وتشغيل التطبيق مرة أخرى:

  1. go build -tags pro
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

هذا لا يزال ليس ما نحتاجه بالضبط: الميزات الشركة تظهر الآن عندما نحاول بناء الإصدار Pro. لحل هذا، نحتاج إلى استخدام بطاقة بناء أخرى. على عكس بطاقة pro، يجب علينا الآن التأكد من أن الميزات pro وenterprise متاحة.

يحسب نظام بناء Go هذه الحالة من خلال السماح باستخدام بعض من المنطق الثابت الأساسي في نظام البطاقات البناء.

دعونا نفتح enterprise.go مجدداً:

  1. nano enterprise.go

أضف بتاجر آخر، enterprise، في نفس السطر الذي تواجد فيه بتاجر pro:

enterprise.go
// +build pro enterprise

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

حفظ وغلق الملف.

الآن دعونا نتجه إلى تجميع وتشغيل التطبيق ببتاجر الجديد enterprise.

  1. go build -tags enterprise
  2. ./app

هذا سيعطينا التالي:

Output
> Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2

والآن لقد فقدنا الميزات المتاحة للبتاجر Pro. وهذا لأنه حينما نضع بتاجرات متعددة في نفس السطر في ملف .go، فيجور go build سيفهمها كاساح المقاربة بالأو من المنطقة. ومع اضافة السطر // +build pro enterprise، سيتم بناء ملف enterprise.go إذا كان موجوداً أي من البتاجر البناء pro أو البتاجر البناء enterprise. نحتاج إلى تعميم البتاجر الصحيحة لتتطلب كلاهما وإستخدام المنطقة المقاربة بالمقاربة بدلاً من الأمر.

بدلاً من وضع الجميع في السطر الواحد، إذا وضعناهما في سطور منفصلة، فيجور go build سيفهم هذه البتاجر بمقاربة المقاربة بالمقاربة بدلاً من الأمر.

افتح enterprise.go مجدداً ودعونا نفصل بتاجر البناء على سطور مختلفة.

enterprise.go
// +build pro
// +build enterprise

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

الآن تجميع وتشغيل التطبيق ببتاجر الجديد enterprise.

  1. go build -tags enterprise
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2

لم نصل بعد إلى المنطقة المناسبة: لأن الأمر يتطلب كلاهما pro و enterprise البتاجر.

دعونا نمارس مجدداً:

  1. go build -tags "enterprise pro"
  2. ./app

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

Output
> Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

الآن يمكن بناء تطبيقنا من نوع واحد من الأشجار المصدرية بطرق متعددة تتحرك قيود الميزات بالتوافق المناسب.

في هذا المثال، استخدمنا وسم جديد // +build لتعريف المنطق البولي (AND), ولكن هناك طرق بديلة لتمثيل المنطق البولي بوسمات البناء. يحتوي جدول المثال التالي على بعض أمثلة للتشكيل السينتاكي لوسمات البناء، وهم متماثلون بالمنطق البولي:

Build Tag Syntax Build Tag Sample Boolean Statement
Space-separated elements // +build pro enterprise pro OR enterprise
Comma-separated elements // +build pro,enterprise pro AND enterprise
Exclamation point elements // +build !pro NOT pro

الخلاصة

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

إذا كنت ترغب في تعلم المزيد عن وسمات البناء، أنظر إلى المستند التعليمي الرسمي لـ Golang حول المواضيع، أو استمر في استكشاف سلسلة ناشرتنا كيف تكون برمجيات بلغة Go.

Source:
https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags