Настройка Go Binaries с тегами сборки

Вступление

В Go тег build или ограничение сборки - это идентификатор, добавляемый в фрагмент кода, который определяет, когда файл должен быть включен в пакет во время процесса + build +. Это позволяет вам создавать разные версии приложения Go из одного и того же исходного кода и быстро и организованно переключаться между ними. Многие разработчики используют теги сборки для улучшения рабочего процесса создания кроссплатформенных совместимых приложений, таких как программы, которые требуют изменений кода для учета различий между различными операционными системами. Теги сборки также используются для тестирования integration, что позволяет быстро переключаться между интегрированным кодом и кодом с помощью https://en.wikipedia.org/wiki/ Mock_object [mock service or stub], и для разных уровней наборов функций в приложении.

Давайте возьмем проблему различных наборов функций клиента в качестве примера. При написании некоторых приложений вам может потребоваться указать, какие функции следует включить в двоичный файл, например приложение, предлагающее уровни * Free *, * Pro * и * Enterprise *. Когда клиент увеличивает уровень своей подписки в этих приложениях, все больше функций становятся разблокированными и доступными. Чтобы решить эту проблему, вы можете поддерживать отдельные проекты и пытаться синхронизировать их друг с другом с помощью операторов + import +. Хотя этот подход будет работать, со временем он станет утомительным и подверженным ошибкам. Альтернативный подход заключается в использовании тегов сборки.

В этой статье вы будете использовать теги сборки в Go для создания различных исполняемых двоичных файлов, которые предлагают наборы функций Free, Pro и Enterprise образца приложения. У каждого будет свой набор функций, по умолчанию бесплатная версия.

Предпосылки

Чтобы следовать примеру в этой статье, вам понадобится:

  • Рабочее пространство Go, настроенное следующим образом Настройка локальной среды программирования.

Сборка бесплатной версии

Начнем с создания бесплатной версии приложения, так как она будет использоваться по умолчанию при запуске + go build + без каких-либо тегов сборки. Позже мы будем использовать теги сборки, чтобы выборочно добавлять другие части в нашу программу.

В каталоге + src + создайте папку с именем вашего приложения. Этот урок будет использовать + app +:

mkdir

Переместить в эту папку:

cd

Затем создайте новый текстовый файл в выбранном вами текстовом редакторе с именем + main.go +:

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)
 }
}

В этом файле мы создали программу, которая объявляет slice с именем + features +, которая содержит два strings, которые представляют функции нашего бесплатного приложения. Функция + main () + в приложении использует https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go#looping-through-sequential-data- types-with-rangeclause [+ for + loop to + range +] через фрагмент + features + и распечатывает все функции, доступные на экране.

Сохраните и выйдите из файла. Теперь, когда этот файл сохранен, нам больше не придется редактировать его до конца статьи. Вместо этого мы будем использовать теги сборки для изменения функций двоичных файлов, которые мы будем строить из него.

Создайте и запустите программу:

go build
./

Вы получите следующий вывод:

Output> Free Feature #1
> Free Feature #2

Программа распечатала две наши бесплатные функции, дополнив бесплатную версию нашего приложения.

Итак, вы создали приложение с очень простым набором функций. Далее вы создадите способ добавления дополнительных функций в приложение во время сборки.

Добавление профессиональных функций с помощью + go build

До сих пор мы избегали внесения изменений в + main.go +, имитирующих общую производственную среду, в которую необходимо добавлять код без изменений и, возможно, не нарушать основной код. Поскольку мы не можем редактировать файл + main.go +, нам потребуется использовать другой механизм для добавления большего количества функций в слайс + features + с помощью тегов сборки.

Давайте создадим новый файл с именем + pro.go +, который будет использовать функцию https://www.digitalocean.com/community/tutorials/understanding-init-in-go [+ init () +], чтобы добавить больше особенности к слайсу + features +:

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:

go build

Поскольку в нашем текущем каталоге теперь есть два файла (+ pro.go + и + main.go +), + go build + создаст двоичный файл из них обоих. Выполните этот двоичный файл:

./

Это даст вам следующий набор функций:

Output> Free Feature #1
> Free Feature #2

Приложение теперь включает в себя как Pro, так и бесплатные функции. Однако это нежелательно: поскольку нет различий между версиями, бесплатная версия теперь включает функции, которые должны быть доступны только в версии Pro. Чтобы это исправить, вы можете добавить больше кода для управления различными уровнями приложения или использовать теги сборки, чтобы указать цепочке инструментов Go, какие файлы + +go + строить, а какие игнорировать. Давайте добавим теги сборки на следующем шаге.

Добавление тегов сборки

Теперь вы можете использовать теги сборки, чтобы отличать Pro-версию вашего приложения от бесплатной версии.

Давайте начнем с изучения того, как выглядит тег сборки:

// +build

Поместив эту строку кода в качестве первой строки вашего пакета и заменив ++ на имя вашего тега сборки, вы пометите этот пакет как код, который можно выборочно включить в окончательный двоичный файл. Давайте посмотрим на это в действии, добавив тег build в файл + pro.go +, чтобы команда + go build + проигнорировала его, если тег не указан. Откройте файл в вашем текстовом редакторе:

nano pro.go

Затем добавьте следующую выделенную строку:

pro.go

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 + `.

Скомпилируйте и снова запустите приложение:

go build
./

Вы получите следующий вывод:

Output> Free Feature #1
> Free Feature #2

Поскольку файл + pro.go + требует наличия тега + pro +, файл игнорируется и приложение компилируется без него.

При выполнении команды + go build мы можем использовать флаг` + -tags + , чтобы условно включить код в скомпилированный источник, добавив сам тег в качестве аргумента. Давайте сделаем это для тега `+ pro +:

go build -tags pro

Это выведет следующее:

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

Теперь мы получаем дополнительные возможности только при сборке приложения с помощью тега сборки + pro +.

Это хорошо, если есть только две версии, но все становится сложнее, когда вы добавляете больше тегов. Чтобы добавить версию Enterprise нашего приложения на следующем шаге, мы будем использовать несколько тегов сборки, объединенных с помощью логической логики.

Build Tag Логическая логика

Когда в пакете Go имеется несколько тегов сборки, они взаимодействуют друг с другом с использованием Boolean logic. Чтобы продемонстрировать это, мы добавим уровень Enterprise нашего приложения, используя тег + pro + и тег + enterprise +.

Чтобы создать двоичный файл Enterprise, нам нужно будет включить как функции по умолчанию, функции уровня Pro, так и новый набор функций для Enterprise. Сначала откройте редактор и создайте новый файл + enterprise.go +, который добавит новые возможности Enterprise:

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 +. Откройте файл в текстовом редакторе:

nano enterprise.go

Затем добавьте тег сборки перед объявлением + package main + и обязательно добавьте новую строку после тега сборки:

enterprise.go

package main

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

Сохраните и выйдите из файла.

Скомпилируйте и запустите приложение без каких-либо тегов:

go build
./

Вы получите следующий вывод:

Output> Free Feature #1
> Free Feature #2

Функции Enterprise больше не отображаются в бесплатной версии. Теперь давайте добавим тег + pro + build и соберем и снова запустим приложение:

go build -tags pro
./

Вы получите следующий вывод:

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 +:

nano enterprise.go

Добавьте еще один тег сборки + enterprise в той же строке, что и тег` + pro`:

enterprise.go

// +build pro

package main

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

Сохраните и закройте файл.

Теперь давайте скомпилируем и запустим приложение с новым тегом сборки + enterprise.

go build -tags enterprise
./

Это даст следующее:

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

Теперь мы потеряли возможности Pro. Это потому, что когда мы помещаем несколько тегов сборки в одну и ту же строку в файле + .go +, + go build + интерпретирует их как использование логики + OR +. С добавлением строки + // + build pro enterprise файл` + enterprise.go + будет собран, если присутствует * либо * тег сборки + pro + , либо тег сборки + + enterprise. Нам нужно правильно настроить теги сборки так, чтобы они требовали * оба * и использовать логику `+ AND +.

Вместо того, чтобы помещать оба тега в одну строку, если мы поместим их в отдельные строки, то + go build + будет интерпретировать эти теги с помощью логики + AND +.

Снова откройте + enterprise.go + и разделите теги сборки на несколько строк.

enterprise.go

package main

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

Теперь скомпилируйте и запустите приложение с новым тегом сборки + enterprise.

go build -tags enterprise
./

Вы получите следующий вывод:

Output> Free Feature #1
> Free Feature #2

Все еще не совсем так: поскольку оператор + AND + требует, чтобы оба элемента считались + true +, нам нужно использовать оба тега + pro + и + enterprise +.

Давай еще раз попробуем:

go build -tags "enterprise pro"
./

Вы получите следующий вывод:

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

Теперь наше приложение может быть построено из одного и того же дерева исходных текстов несколькими способами, соответственно открывая функции приложения.

В этом примере мы использовали новый тег + // + build для обозначения логики` + AND`, но есть альтернативные способы представления логической логики с помощью тегов build. В следующей таблице приведены некоторые примеры другого синтаксического форматирования для тегов сборки, а также их логический эквивалент:

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 +, затем вы объединили несколько тегов с булевой логикой. Затем вы создали программу, которая представляла различные наборы функций в версиях Free, Pro и Enterprise, демонстрируя мощный уровень контроля, который теги могут дать вам над вашим проектом.

Если вы хотите узнать больше о тегах сборки, посмотрите документацию Golang или продолжите изучение нашего https: //www.digitalocean.com/community/tutorial_series/how-to-code-in-go[How To Code in Go series].