כיבוד בינאריים של Go עם תגיות בניה

הקדם

בגו, תווית בניית תווי בניית, או הגבלה בנייתית, היא מפיק מסומן שנוסף לקטע קוד שמחליט מתי הקובץ צריך להיות כלול בארגז בזמן תהליך הבניית. זה מאפשר לך לבנות גורמים שונים של היישום הגו מאותו קוד מקורי ולהחליף בינהם באופן מהיר ומאורגן. מומחים רבים משתמשים בתווים בניית כדי לשפר את העבודה של בניית יישומים סולאריים מתאימים, כמו תוכנות שדורשות שינויים בקוד על מנת להתייחס להבדלים בין מערכות ההפעלה השונות. תווים בניית משמשים גם לבניית בדיקות התאמה, מאפשר לך להחליף בין הקוד המאוחד והקוד עם שירות מומץ או חיקוץ, ולרמות שונות של מערכות תכונות בתוכו של היישום.

א�פילו את הבעיה של ייחודיות התכונות של הלקוחות כדוגמה. כשאתה כותב יישומים מסויימים, אולי תרצה לשלוט אילו תכונות לכלול בקובץ הבינארי, כמו יישום שמציע רמות חינם, פרו ו-אנטרפריז. ככל שהלקוח מגדיל את רמת החברה שלו באותם יישומים, תכונות נוספות נפתחות ונזמינות. לפתור את הבעיה הזו, תוכל לשמור פרוייקטים נפרדים ולנסות לשמור אותם בסנכרון עם זה אחר דרך השימוש בהצהרות import. בעוד שהגישה הזו תעבוד, במשך הזמן היא תהפוך למשעמם ולשגיאות. גישה 書ית תהיה השימוש בתגי בניה.

במאמר זה, תשתמש בתגי בניה בגו כדי ליצור בינאריים בריאניים שונים שמציעים סטי תכונות חינם, פרו ואנטרפריז של יישום דוגמה. כל אחד יהיה בעל סט תכונות שונה שנזמן, עם הגרסה החינמית כברירת מחדל.

הדרישות הקדם

כדי לעקוב אחר הדוגמה במאמר זה, תצטרך:

בניית הגירסה החינמית

בואו נתחיל בבניית הגירסה החינמית של היישום, כי זו תהיה הברירת המחדל כאשר מפעילים 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)
  }
}

בקובץ הזה, יצרנו תוכנית שמכריזה על מקבץ בשם features, שמכיל שני מחרוזות שמייצגות את התכונות של היישום החינמי שלנו. הפונקציה main() ביישום משתמשת בלולאת for כדי לעבור עם range על המקבץ features ולהציג את כל התכונות הזמינות על המסך.

שמור וצא מהקובץ. עכשיו שהקובץ הזה נשמר, לא נצטרך יותר לערוך אותו למשך המאמר הנוסף. במקום זה נשתמש בתגי יצור כדי לשנות את התכונות של הבינארים שנבנה ממנו.

בנה והפעל את התוכנית:

  1. go build
  2. ./app

תקבל את הפלט הבא:

Output
> Free Feature #1 > Free Feature #2

התוכנית הדפיסה את שתי התכונות החינמיות שלנו, השלים את גירסת החינם של האפליקציה שלנו.

עד כה, יצרת יישום שיש לו מערך תכונות מאוד בסיסי. השלב הבא, תיצור דרך להוסיף יותר תכונות ליישום בזמן הבנייה.

הוספת התכונות של Pro עם 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 לבנות ואילו להתעלם. בא נוסיף תגי תבנית בשלב הבא.

הוספת תגי תבנית

אתה יכול עכשיו להשתמש בתגי תבנית כדי להבחין בין גירסת Pro ובין גירסת החינמית של היישום שלך.

בואו נתחיל בבחינה מה נראה תג תבנית:

// +build tag_name

שמים את השורה הזו של קוד כשורה ראשונה בחבילה שלך ומחליפים tag_name עם השם של התג הבנייה שלך, תסמינו את החבילה הזו כקוד שיכול להיכלל באופן בחירתי בבינאר הסופי. בואו נראה את זה בפעולה על-ידי הוספת תג בנייה לקובץ 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 מפרשת את זה כהערה. הצהרות תגי בנייה חייבות גם להיות בראש הקובץ .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 כדי לכלול בחירה קוד במקור המקובץ המקובץ על-ידי הוספת התג עצמו

  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. במצב זה, היה צריך רק תג בנייה אחד כדי להשלים את המטרה. כשמוסיפים את התכונות החדשות של Enterprise, צריך ראשית גם לקבל את התכונות של 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

התכונות של Enterprise כבר לא מופיעות בגירסה החינמית. עכשיו, הוסף את התג 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

זה עדיין לא בדיוק מה שאנחנו צריכים: התכונות של Enterprise מופיעות כשאנחנו מנסים לבנות את הגירסה של 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 על הנושא, או תמשיך לחקור את סדרת הדרכות שלנו How To Code in Go.

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