Как создать файл env go

Обновлено: 05.07.2024

При разработке программного обеспечения очень важно учитывать операционную систему и архитектуру процессора, для которого вы будете компилировать ваш бинарный файл. Поскольку часто бывает очень трудно или просто невозможно запустить один бинарный файл на разных ОС/архитектурах, довольно распространенной практикой является сборка итогового бинарного файла для набора различных платформ для максимального увеличения аудитории вашей программы. Однако это может оказаться затруднительным, когда платформа, которую вы используете для разработки, отличается от платформы, где вы хотите развернуть вашу программу. В прошлом, например, при разработке программы на Windows и ее последующем развертывании на компьютере с Linux или macOS могла требоваться настройка инструмента для сборки для каждой среды, где вам требуется бинарный файл. Кроме того, вам нужно поддерживать ваш инструментарий в синхронизированном состоянии, а также учитывать другие моменты, что будет приводить к росту издержек и затруднит совместное тестирование и распространение.

Go решает эту проблему посредством поддержки различных платформ напрямую в инструменте go build , а также в остальной цепочке инструментов Go. Используя переменные среды и теги сборки, вы можете контролировать, для какой ОС и архитектуры предназначен ваш бинарный файл, а также реализовать рабочий процесс, который позволит быстро добавлять предназначенный для конкретной платформы код без внесения изменений в базу вашего кода.

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

Предварительные требования

Для выполнения примера из этой статьи вам потребуется следующее:

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

Возможные платформы GOOS и GOARCH

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

Инструменты Go имеют команду, которая может вывести список поддерживаемых Go платформ для сборки. Этот список может меняться с каждым новым релизом Go, так что описанные здесь комбинации могут быть иными в другой версии Go. На момент написания настоящего руководства текущая версия Go — 1.13 .

Чтобы просмотреть список поддерживаемых платформ, запустите следующую команду:

Вы получите примерно следующий результат:

Данный вывод — это набор пар ключ-значение, разделенных / . Первая часть комбинации перед символом / — это операционная система. В Go эти операционные системы — это возможные значения для переменной среды GOOS , произносится “goose”, название которой означает операционная система Go. Вторая часть, идущая после / , — это архитектура. Как и в случае с операционной системой, это все возможные значения для переменной среды: GOARCH . Это сокращение произносится “gore-ch” и означает архитектура Go.

Давайте разберем одну из этих комбинаций, чтобы понять, что это означает и как работает, воспользовавшись linux/386 в качестве примера. Пара ключ-значение начинается с переменной GOOS , которая в этом случае будет linux , то есть ОС Linux. Для GOARCH здесь указано значение 386 , что означает микропроцессор Intel 80386.

Существует множество доступных для команды go build платформ, но в большинстве случаев вы будете использовать linux , windows или darwin в качестве значения для GOOS . Это позволяет покрыть три важнейшие платформы OS: Linux, Windows и macOS, которая основана на операционной системе Darwin и поэтому называется darwin . Однако Go позволяет охватить и менее популярные платформы, например nacl , т. е. Native Client от Google.

Когда вы запускаете команду, например go build​​​ , Go использует GOOS и GOARCH для определения способа сборки бинарного файла. Чтобы узнать, какая конфигурация у вашей платформы, вы можете использовать команду go env и передать GOOS и GOARCH в качестве аргументов:

При тестировании этого примера мы запускаем эту команду в macOS на компьютере с архитектурой AMD64, поэтому мы получим следующее:

Здесь вывод команды указывает нам, что в нашей системе GOOS=darwin и GOARCH=amd64 .

Теперь вы знаете, что такое GOOS и GOARCH в Go, а также их возможные значения. Далее вы выполните сборку программы для использования в качестве примера использования этих переменных среды и меток сборки для получения бинарных файлов для других платформ.

Написание платформо-зависимой программы с помощью filepath.Join()

Прежде чем начать сборку бинарных файлов для других платформ, мы создадим пример программы. Для этой задачи отлично подходит функция Join в пакете path/filepath в стандартной библиотеке Go. Эта функция получает ряд строк и возвращает одну строку, к которой добавлен соответствующий разделитель пути файла.

Это отличный пример программы, поскольку работа программы зависит от того, в какой ОС она запущена. Для Windows разделитель пути файла — это обратный слэш \​​​ , а в системах Unix используется прямой слэш / .

Давайте начнем сборку приложения, которое использует filepath.Join() , а затем вы напишете свою собственную реализацию функции Join() , которая настраивает код в соответствии с платформой.

Во-первых, создайте папку в директории src с именем вашего приложения:

Перейдите в эту директорию:

Далее создайте новый файл в текстовом редакторе по вашему выбору с именем main.go . В этом обучающем руководстве мы будем использовать Nano:

После открытия файла добавьте следующий код:

Функция main() в этом файле использует filepath.Join() для конкатенации трех строк вместе с правильным платформо-зависимым разделителем пути.

Сохраните и закройте файл, а затем запустите программу:

При запуске этой программы вы получите разный вывод в зависимости от того, какую платформу вы используете. В Windows вы увидите, что строки будут разделены \ :

В системах Unix, в том числе macOS и Linux, вы получите следующее:

Это означает, что из-за разных протоколов файловой системы, используемых в этих операционных системах, программа должна будет выполнять разный код для различных платформ. Однако поскольку в ней уже используется разный разделитель пути файла в зависимости от операционной системы, мы знаем, что filepath.Join() уже учитывает различие в платформе. Это вызвано тем, что цепь инструментов Go автоматически определяет GOOS и GOARCH на вашем компьютере и использует эту информацию для применения сниппета кода с правильными маркерами сборки и разделителем файла.

Давайте рассмотрим, откуда функция filepath.Join() получает нужный разделитель. Запустите следующую команду для просмотра соответствующего сниппета из стандартной библиотеки Go:

В результате вы увидите содержимое path_unix.go . Найдите следующую часть файла:

В этом разделе определяется PathSeparator для всех разновидностей Unix-систем, которые поддерживает Go. Обратите внимание на все маркеры сборки сверху, каждый из которых является одним из возможных значений платформ Unix для GOOS . Когда GOOS соответствует этим терминам, ваша программа будет выводить разделитель файла в стиле Unix.

Нажмите q для возврата к командной строке.

Далее откройте файл, который определяет поведение filepath.Join() при использовании в Windows:

Вы увидите следующее:

Хотя здесь значение PathSeparator будет \\ , код будет отображать отдельный обратный слэш ( \ ), необходимый для путей файлов в Windows, поскольку первый обратный слэш требуется только в качестве символа перехода.

Обратите внимание, что в отличие от файла Unix, сверху нет меток сборки. Это объясняется тем, что GOOS и GOARCH также могут быть переданы команде go build , добавив нижнее подчеркивание ( _ ) и значение переменной среды в качестве суффикса для имени файла. Мы обсудим это подробнее в разделе Использование суффиксов имен файлов GOOS и GOARCH. Здесь часть _windows названия имени path_windows.go заставляет файл вести себя так, будто у него есть маркер сборки // +build windows в верхней части файла. В связи с этим, когда ваша программа запускается в Windows, она будет использовать константы PathSeparator и PathListSeparator из сниппета кода path_windows.go .

Чтобы вернуться к командной строке, выйдите из less , нажав q .

На этом шаге вы создали программу, показывающую, как Go автоматически преобразовывает GOOS и GOARCH в маркеры сборки. Держа это в уме, вы можете обновить вашу программу и написать свою собственную реализацию filepath.Join() , используя маркеры сборки, чтобы вручную задать правильный PathSeparator для платформ Windows и Unix.

Реализация платформенно-зависимой функции

Теперь, когда вы знаете, как стандартная библиотека Go имплементирует специфичный для платформы код, вы можете использовать маркеры сборки, чтобы сделать это в вашей собственной программе app . Для этого вам нужно будет написать свою собственную реализацию filepath.Join() .

Откройте ваш файл main.go :

Замените содержимое main.go на следующее, используя свою собственную функцию с именем Join() :

Функция Join получает ряд частей и объединяет их вместе с помощью метода strings.Join() из пакета strings для конкатенации частей , используя PathSeparator .

Вы еще не определили PathSeparator , поэтому давайте сделаем это в другом файле. Сохраните и выйдите из main.go , откройте ваш любимый редактор и создайте новый файл с именем path.go :

Определите PathSeparator и установите его равным разделителю пути файла Unix / :

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

Вывод должен выглядеть следующим образом:

Это значит, что программа успешно запускается для получения пути файла в стиле Unix. Однако это еще не то, что нам нужно: вывод всегда будет a/b/c , вне зависимости от того, на какой платформе программа запущена. Чтобы добавить функционал создания пути файла в стиле Windows, вам нужно добавить версию PathSeparator для Windows и указать команде go build , какую версию следует использовать. В следующем разделе вы сможете воспользоваться маркерами сборки, чтобы выполнить эту задачу.

Использование маркеров GOOS или GOARCH

Чтобы учитывать платформы Windows, вы создадите альтернативный файл для path.go и будете использовать маркеры сборки, чтобы убедиться, что сниппеты кода запускаются, только когда GOOS и GOARCH принадлежат к соответствующей платформе.

Однако сначала нужно добавить маркер сборки в path.go , чтобы указать ему на необходимость выполнять сборку для любых платформ, кроме Windows. Откройте файл:

Добавьте в файл выделенный маркер сборки:

Маркеры сборки Go позволяют использовать инвертирование, что означает, что вы можете указать Go выполнить сборку этого файла для любой платформы, кроме Windows. Чтобы инвертировать маркер доступа, добавьте ! перед маркером.

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

Теперь, если бы вы захотели запустить эту программу в Windows, то получили бы следующую ошибку:

В данном случае Go не сможет включить path.go для определения переменной PathSeparator .

Теперь, когда вы убедились, что path.go не будет запускаться, когда для GOOS используется значение Windows, добавьте новый файл, windows.go :

В файле windows.go необходимо определить PathSeparator для Windows, а также маркер сборки, чтобы команда go build смогла понимать, что это реализация для Windows:

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

Хотя теперь сборка бинарных файлов будет выполняться корректно для соответствующих платформ, есть и другие изменения, которые нужно внести для выполнения компиляции для платформы, к которой у вас нет доступа. Для этого на следующем шаге нам нужно будет изменить локальные переменные GOOS и GOARCH .

Использование ваших локальных переменных среды GOOS и GOARCH

Ранее вы запускали команду go env GOOS GOARCH для получения информации о том, в какой ОС и с какой архитектурой вы работаете. При запуске команды go env выполняется поиск двух переменных среды GOOS и GOARCH ; если их удалось найти, будут использоваться их значения, но если они не были найдены, Go будет использовать для них информацию для текущей платформы. Это означает, что вы можете изменить значения GOOS или GOARCH , чтобы они не совпадали по умолчанию с данными локальной операционной системы и архитектуры.

Команда go build ведет себя примерно так же, как и команда go env . Вы можете задать для переменных среды GOOS или GOARCH значение для получения сборки для другой платформы с помощью команды go build .

Если вы не используете систему Windows, создайте бинарный файл windows для app , установив для переменной среды GOOS значение windows при запуске команды go build :

Теперь вы можете вывести файлы в вашей текущей директории:

Вывод списка файлов в директории теперь показывает, что в директории проекта есть исполняемый файл app.exe для Windows:

Используя команду file , вы можете получить дополнительную информацию об этом файле, подтвердив его сборку:

Вы получите следующий результат:

Также вы можете задать значение для одной или обеих переменных среды во время сборки. Запустите следующую команду:

Теперь ваш исполняемый файл app будет заменен файлом для другой архитектуры. Запустите команду file для этого бинарного файла:

Вывод будет выглядеть следующим образом:

Задав значения для ваших локальных переменных среды GOOS и GOARCH , вы можете выполнить сборку бинарных файлов для любой из совместимых с Go платформ без сложной конфигурации или настройки. Далее вы будете использовать соглашения для имен файлов, чтобы четко организовать ваши файлы, и выполнять сборку для конкретных платформ автоматически без маркеров для сборки.

Использование суффиксов файлов имен GOOS и GOARCH

Как вы уже видели ранее, в стандартной библиотеке Go активно используются маркеры сборки для упрощения кода, что позволяет разделять реализации для разных платформ в разных файлах. Когда вы открывали файл os/path_unix.go , там был маркер сборки, который содержал список всех возможных комбинаций, рассматриваемых в качестве Unix-платформ. Однако в файле os/path_windows.go отсутствуют маркеры для сборки, поскольку суффикса в имени файла достаточно, чтобы Go мог понять, для какой платформы предназначен этот файл.

Давайте рассмотрим синтаксис этого элемента. При присвоении имени файла .go вы можете добавить GOOS и GOARCH в качестве суффиксов к имени файла в этом порядке, отделяя значения нижним подчеркиванием ( _ ). Если у вас есть файл Go с именем filename.go , вы можете указать ОС и архитектуру, изменив имя файла на filename_ GOOS _ GOARCH .go . Например, если вы хотите скомпилировать его для Windows с 64-битной архитектурой ARM, вы должны использовать имя файла filename_windows_arm64.go . Такое соглашение о наименованиях помогает поддерживать код в организованном виде.

Обновите вашу программу для использования суффиксов имени файла вместо маркеров сборки. Во-первых, переименуйте файл path.go и windows.go для использования соглашения, используемого в пакете os :

После изменения имен двух файлов вы можете удалить маркер сборки, который вы добавили в path_windows.go :

Удалите // +build windows , чтобы ваш файл выглядел следующим образом:

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

Поскольку unix — это недействительное значение для GOOS , суффикс _unix.go не будет иметь значение для компилятора Go. Однако он передает предполагаемое назначение файла. Как и в файле os/path_unix.go , ваш файл path_unix.go все еще требует использования маркеров для сборки, поэтому этот файл будет сохранен без изменений.

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

Заключение

Возможность генерации бинарных файлов для различных платформ, не требующих зависимостей, является очень ценной функцией цепочки инструментов Go. В этом обучающем руководстве вы использовали эту возможность, добавляя маркеры сборки и суффиксы для имен файлов, чтобы пометить определенные сниппеты кода, которые будут компилироваться только для определенных архитектур. Вы создали собственную платформо-зависимую программу, а затем выполняли манипуляции с переменными среды GOOS и GOARCH для получения бинарных файлов для других платформ, помимо вашей текущей платформы. Это очень ценная возможность, поскольку очень часто используется процесс непрерывной интеграции, который автоматически запускается с помощью этих переменных среды для сборки бинарных файлов для всех платформ.

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

[Изучение языка Go с нуля] 4. Интерпретация общих команд Go

[Изучение языка Go с нуля] 4. Интерпретация общих команд Go


1. Интерпретация команды go hlep

Если вы играли в linux, вам следовало использовать эту команду help, а наш язык go также имеет несколько полезных инструментов в терминале.

Выполните следующую команду go help, чтобы просмотреть справку по команде go

Выполнение выполнено успешно, дисплей выглядит следующим образом

Вот некоторые связанные объяснения его предыдущих команд:

1.1 команда go env

Команда go env используется для печати информации о среде языка Go.


Выполнение выполнено успешно, как показано ниже.

1.2 команда go run

Команда go run используется для компиляции и запуска исходного файла команды. Если вы используете vim для редактирования файла go и хотите, чтобы он запускался временно, чтобы увидеть эффект, используйте эту команду: go run file_name


Выполнение выполнено успешно, как показано ниже.

1.3 получить команду

Команда go get используется для загрузки или обновления указанного пакета кода и зависимых от него пакетов из Интернета в соответствии с требованиями и фактическими условиями, а также для их компиляции и установки. Когда вам нужны сторонние пакеты, такие как gin веб-фреймворка, вам нужно использовать эту команду для загрузки, аналогично python pip


Успешное выполнение, как показано на рисунке ниже

1.4 команда go build

Команда go build используется для компиляции указанных нами исходных файлов или пакетов кода и их зависимых пакетов.

Выполнение выполнено успешно, как показано ниже.

После выполнения команды в ее каталоге будет создан исполняемый файл Unix, как показано ниже.

1.5 команда go install

Команда go install используется для компиляции и установки указанных пакетов кода и зависимых от них пакетов. Эта команда по умолчанию устанавливается в переменной GOBIN. Если она пуста, она устанавливается в GOPATH. Вы можете проверить расположение переменной через go env.


Выполнение выполнено успешно, как показано ниже.

1.6 команда go clean

Команда go clean используется для удаления некоторых файлов и каталогов, созданных при выполнении других команд.Файлы, скомпилированные с помощью сборки, могут быть напрямую: go clean очистить все файлы или добавить -i для очистки файлов, скомпилированных и установленных с помощью установки




1.7 команда go test

Команда go test используется для тестирования программ, написанных на языке Go, и для тестирования написанных пакетов или программ: go test file_name


Выполнение выполнено успешно, как показано ниже.

1.8 команда go list

Команда Go list используется для вывода информации об указанном пакете кода.


Выполнение выполнено успешно, как показано ниже.

Интеллектуальная рекомендация

совместный запрос mysql с тремя таблицами (таблица сотрудников, таблица отделов, таблица зарплат)

1. Краткое изложение проблемы: (внизу есть инструкция по созданию таблицы, копирование можно непосредственно практиковать с помощью (mysql)) Найдите отделы, в которых есть хотя бы один сотрудник. Отоб.


[Загрузчик классов обучения JVM] Третий день пользовательского контента, связанного с загрузчиком классов


IP, сеанс и cookie

Язык программирования Go поставляется с богатым набором инструментов, что значительно упрощает создание пакетов и исполняемых файлов. Одной из самых мощных функций Go является возможность перекрестной сборки исполняемых файлов для любой платформы, поддерживаемой Go. Это облегчает тестирование и распространение пакетов, потому что для этого не нужно иметь доступ к определенной платформе.

Данное руководство научит пользоваться инструментами Go, получать пакеты из контроля версий и устанавливать исполняемые файлы автоматически и вручную. Также вы узнаете, как собирать исполняемые файлы для различных архитектур и автоматизировать процесс сборки (например, для Windows и macOS).

Требования

  • Сервер Ubuntu 16.04.
  • Пользователь с доступом к sudo.
  • Настроенный брандмауэр (читайте руководство по начальной настройке).
  • Установленный Go (инструкции можно найти в этом руководстве).

1: Установка программ Go из контроля версий

Прежде чем начать создавать исполняемые файлы из пакета Go, необходимо получить его исходный код. Инструмент go get может извлекать пакеты из систем управления версиями, таких как GitHub. Команда go get клонирует пакеты в подкаталоги $GOPATH/src/. Затем, если это возможно, она устанавливает пакет, создавая его исполняемый файл и помещая его в каталог $GOPATH/bin.

Если вы настроили Go, как описано в этом руководстве, каталог $GOPATH/bin включен в переменную окружения $PATH; это значит, что вы можете использовать установленные пакеты из любой точки системы.

go get package-import-path

где строка package-import-path – уникальный идентификатор пакета. Часто это местонахождение пакета в удаленном репозитории типа Github или подкаталог $GOPATH/src/ на локальной машине.

В команде go get часто используется флаг –u, который загружает зависимости (или обновляет их, если они уже есть на машине).

Для примера попробуйте установить Caddy, веб-сервер, написанный на Go.

На установку уйдет некоторое время. Отсутствие вывода указывает, что команда выполнена успешно.

which caddy
/home/8host/work/bin/caddy

Примечание: Команда go get устанавливает пакеты из стандартной ветки репозитория Git, обычно это ветка master. Ознакомьтесь с инструкциями по работе с пакетом в файле README.

Чтобы выбрать другую ветку, используйте команду git checkout.

2: Сборка исполняемого файла

Команда go get загрузила исходный код и установила исполняемый файл Caddy. Если вы хотите пересобрать исполняемый файл или собрать его из собственного кода, используйте команду go build.

Хотя веб-сервер Caddy уже установлен, попробуйте собрать его вручную, чтобы ознакомиться с этим процессом.

Как и ранее, отсутствие вывода означает, что команда была выполнена успешно. Исполняемый файл будет сгенерирован в текущем каталоге и унаследует его имя. В этом случае исполняемый файл будет называться caddy.

Если вы находитесь в каталоге пакета, вы можете опустить путь к пакету и просто запустить go build.

Чтобы указать другое имя или место для исполняемого файла, используйте флаг -o. Попробуйте создать исполняемый файл caddy-server и поместить его в каталог build в текущем рабочем каталоге:

Команда создаст исполняемый файл и каталог ./build (если его не существует).

3: Установка исполняемых файлов

Процесс сборки создает исполняемый файл в текущем (или в другом) каталоге. Установка исполняемого файла – это процесс создания исполняемого файла и его сохранения в $GOPATH/bin. Команда go install работает так же, как go build, но размещает выходной файл в нужном месте.

Чтобы установить исполняемый файл, укажите в команде go install путь импортируемого пакета. Например:

Исполняемый файл наследует имя каталога, в котором хранится пакет. На этот раз исполняемый файл хранится в $GOPATH/bin. Если $GOPATH/bin указан в переменной окружения $PATH, исполняемый файл будет доступен из любой точки вашей операционной системы. Вы можете проверить его местоположение:

which caddy
/home/8host/work/bin/caddy

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

4: Создание исполняемых файлов для разных архитектур

Команда go build позволяет собирать на вашей платформе исполняемые файлы для любой целевой платформы, которую поддерживает Go. Это означает, что вы можете тестировать, выпускать и распространять свое приложение, не создавая эти исполняемые файлы на целевых платформах, которые вы хотите использовать.

env GOOS=target-OS GOARCH=target-architecture go build package-import-path

Команда env запускает программу в измененной среде. Это позволяет использовать переменные среды только для текущего выполнения команды. После выполнения команды переменные будут сброшены или переустановлены.

В этой таблице вы найдете возможные комбинации GOOS и GOARCH

GOOS – целевая ОС GOARCH – целевая платформа
android arm
darwin 386
darwin amd64
darwin arm
darwin arm64
dragonfly amd64
freebsd 386
freebsd amd64
freebsd arm
linux 386
linux amd64
linux arm
linux arm64
linux ppc64
linux ppc64le
linux mips
linux mipsle
linux mips64
linux mips64le
netbsd 386
netbsd amd64
netbsd arm
openbsd 386
openbsd amd64
openbsd arm
plan9 386
plan9 amd64
solaris amd64
windows 386
windows amd64

Важно! Для кросскомпиляции исполняемых файлов для Android требуется Android NDK, а также некоторые дополнительные настройки, которые не входят в данное руководство.

Используя значения в таблице, можно построить Caddy для 64-битной системы Windows:

Исполняемый файл будет создан в текущем каталоге и унаследует имя пакета. Поскольку этот исполняемый файл предназначен для Windows, имя заканчивается суффиксом .exe.

Файл caddy.exe появится в текущем каталоге, это можно проверить с помощью команды ls.

ls caddy.exe
caddy.exe

Примечание: С помощью флага –о можно переименовать или переместить исполняемый файл. Переименовывая исполняемые файлы для Windows, не забудьте добавить суффикс .exe.

5: Сценарий для автоматической кросскомпиляции

Процесс создания исполняемых файлов для многих платформ может занять немало времени и сил, но его можно автоматизировать с помощью сценария.

Сценарий будет принимать путь импортируемого пакета в качестве аргумента, перебирать предопределенный список пар операционных систем и платформ и генерировать исполняемый файл для каждой пары, помещая вывод в текущий каталог. Каждый исполняемый файл будет наследовать имя пакета, а также указывать целевую платформу и архитектуру. Этот универсальный сценарий можно использовать в любом проекте.

Перейдите в домашний каталог и создайте файл go-executable-build.bash.

.
if [[ -z "$package" ]]; then
echo "usage: $0 <package-name>"
exit 1
fi

Примечание: Если вы хотите, чтобы этот сценарий работал с предопределенным пакетом, измените переменную package и укажите путь к пакету:

Затем нужно извлечь из пути имя пакета. Путь импортируемого пакета разделяется слешами (/), а имя пакета находится в самом конце. Для начала нужно преобразовать путь в массив с помощью разделителя /.

Имя пакета должно быть последним элементом нового массива $package_split. В Bash можно использовать отрицательный индекс массива, чтобы получить доступ к данным с конца, а не с начала. Добавьте эту строку, чтобы извлечь имя пакета из массива и сохранить его в переменной package_name:

Теперь нужно решить, для каких платформ и архитектур необходимо создавать исполняемые файлы. В этом примере показано, как создать исполняемые файлы для 64-битной MacOS, 64-битной и 32-битной системы Windows. Поместите целевые платформы в массив согласно формату OS/Platform. Каждую пару можно разделить на переменные GOOS и GOARCH, используя тот же метод, который использовался для извлечения имени пакета из пути. Добавьте платформы в сценарий:

.
platforms=("windows/amd64" "windows/386" "darwin/amd64")

Затем нужно выполнить итерацию массива платформ и разделить каждую запись на значения для переменных среды GOOS и GOARCH; их можно использовать для создания исполняемого файла. Для этого добавьте цикл for:

Затем сгенерируйте имя исполняемого файла, объединив имя пакета с ОС и архитектурой. Файлы для Windows должны содержать суффикс .exe. Добавьте этот код в цикл for:

Установив переменные, можно использовать команду go build для создания исполняемого файла. Добавьте эту строку в тело цикла for перед ключевым словом done:

.
if [ $GOOS = "windows" ]; then
output_name+='.exe'
fi
env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
done

Наконец, нужно обеспечить обработку ошибок при создании исполняемого файла. Например, Go может столкнуться с ошибкой, если попытается создать пакет, для которого нет исходного кода. Можно проверить код возврата команды go build для ненулевого значения. Переменная $? содержит код возврата выполнения предыдущей команды. Если go build возвращает 0, значит, возникла проблема и сценарий прекратит работу. Добавьте этот код в цикл for, после команды go build и перед done.

.
env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
if [ $? -ne 0 ]; then
echo 'An error has occurred! Aborting the script execution. '
exit 1
fi

Теперь у вас есть сценарий, который будет собирать разные исполняемые файлы из пакетов Go. Вот полный код сценария:

Убедитесь, что ваш сценарий выглядит так же. Сохраните и закройте файл.

Сделайте сценарий исполняемым:

chmod +x go-executable-build.bash

Протестируйте работу сценария. Соберите исполняемый файл для Caddy:

Если сценарий выполнен правильно, в текущем каталоге появятся исполняемые файлы. Отсутствие вывода означает, что сценарий выполнен успешно. Проверьте исполняемые файлы:

ls caddy*
caddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe

Чтобы изменить целевые платформы, измените значение переменной platforms.

Заключение

Теперь вы умеете пользоваться базовыми командами Go и выполнять кросскомпиляцию исполняемых файлов.

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

Чтобы убедиться, что приложение работает правильно, вы можете использовать Travis-CI и AppVeyor для тестирования в Windows.


При запуске нового проекта самые большие трудности у меня всегда вызывала его настройка. Всегда стараешься сделать её «идеальной»:

  • используешь лучшую структуру каталогов, чтобы всё было легко найти и импортирование происходило без проблем;
  • настраиваешь все команды так, чтобы нужные действия выполнялись в один клик или с вводом одной команды;
  • находишь лучший инструмент контроля качества кода, средство форматирования, среду тестирования для используемого в проекте языка и библиотеки…

Этот список можно продолжать и продолжать, и всё равно до идеальной настройки будет ещё далеко… Но, по моему скромному мнению, эта настройка для Golang просто лучшая!

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

Первым делом обратимся к структуре каталогов нашего проекта. Здесь у нас несколько файлов верхнего уровня и четыре каталога:

  • pkg — это пакет Go, который содержит только строку версии global. Меняется на версию из хэша текущей фиксации при проведении сборки;
  • config — конфигурационный каталог, который содержит файлы со всеми необходимыми переменными среды. Вы можете использовать любой тип файла, но я бы рекомендовал файлы YAML: их проще читать;
  • build — в этой директории у нас все скрипты оболочки, необходимые для сборки и тестирования приложения, а также создания отчётов для инструментов анализа кода;
  • cmd — фактический исходный код. По правилам именования исходный каталог называется cmd . Внутри есть ещё один каталог с именем проекта (в нашем случае blueprint ). В свою очередь, внутри этого каталога находится main.go , запускающий всё приложение. Также здесь можно найти все остальные исходные файлы, разделённые на модули (подробнее об этом далее).

Оказываетс я , многие предпочитают помещать исходный код в каталоги internal и pkg . Я думаю, что это лишнее: достаточно использовать для этого cmd , где для всего есть своё место.

Помимо каталогов, есть ещё большое количество файлов, о которых мы поговорим в статье.

В проектах Go используются самые разные стратегии управления зависимостями. Однако с версии 1.11 Go обзавёлся официальным решением. Все наши зависимости приводятся в файле go.mod , в корневом каталоге. Вот как он может выглядеть:

Вы можете спросить: «А как в этот файл включить зависимости?». Очень просто, всего одной командой:

Эта команда переустанавливает vendor каталог основного модуля для включения всех пакетов, необходимых для сборки и тестирования каждого пакета модуля исходя из состояния файлов go.mod и исходного кода Go.

И вот наконец мы добрались до исходного кода. Как уже говорилось, исходный код разделён на модули. Модуль представляет собой каталог внутри исходного корневого каталога. В каждом модуле находятся исходные файлы вместе с соответствующими файлами тестов. Например:

Такая структура способствует лучшей читаемости и лёгкости сопровождения кода: он идеально разделён на части, которые проще просматривать. Что касается конфигурации, в этой настройке используем библиотеку конфигураций Go Viper, которая может иметь дело с разными форматами, параметрами командной строки, переменными среды и т.д.

Посмотрим, как мы используем этот Viper здесь. Вот пакет config :

Он состоит из единственного файла. Объявляет один struct , который содержит все переменные конфигурации и имеет одну функцию LoadConfig , которая загружает конфигурацию. Требуется путь до конфигурационных файлов, в нашем случае используем путь до каталога config , который находится в корневом каталоге проекта и содержит наши YAML файлы. И как их будем использовать? Запустим первым делом в main.go :

Что важнее всего после кода? Тесты. Чтобы писать много хороших тестов, нужна настройка, с которой это будет делать легко. Для этого мы используем цель Makefile под названием test , которая собирает и выполняет все тесты в подкаталогах cmd (все файлы с расширением _test.go ). Эти тесты кэшируются, так что их запуск происходит только при наличии изменений в соответствующей части кода. Это очень важно: если тесты будут слишком медленными, рано или поздно вы перестанете их запускать и сопровождать. Помимо модульного тестирования, make test помогает следить за общим качеством кода, запуская с каждым тестовым прогоном gofmt и go vet . gofmt способствует правильному форматированию кода, а go vet помогает с помощью эвристических алгоритмов выявлять в коде любые подозрительные конструкции. Вот пример того, что может получиться в результате выполнения:

Многие говорят, что у них запуск невозможен в облаке, а только на компьютере. Здесь есть простое решение: всегда запускаться в контейнере docker . Делаете ли вы сборку, запускаете ли или тестируете — делайте всё это в контейнере. Кстати, что касается тестирования, make test выполняется тоже только в docker .

Посмотрим, как это происходит. Начнём с файлов Dockerfile из корневого каталога проекта: один из них для тестирования ( test.Dockerfile ), а другой — для запуска приложения ( in.Dockerfile ):

  • test.Dockerfile - в идеале нам было бы достаточно одного файла Dockerfile для запуска приложения и тестирования. Но во время тестовых прогонов нам может потребоваться внести небольшие изменения в среде выполнения, поэтому у нас здесь есть образ для установки дополнительных инструментов и библиотек. Предположим, например, что мы подключаемся к базе данных. Нам не нужно поднимать весь PostgreSQL-сервер при каждом тестовом прогоне или зависеть от какой-нибудь базы данных на хост-машине. Мы просто используем для тестовых прогонов базу данных в памяти SQLite. И если дополнительные установки не понадобятся нашим тестам, то двоичным данным в SQLite они будут очень даже кстати: устанавливаем gcc и g++ , переключаем флажок на CGO_ENABLED , и готово.
  • in.Dockerfile - если посмотреть на этот Dockerfile в репозитории, что мы увидим: просто несколько аргументов и копирование конфигурации в образ. Но что здесь происходит? in.Dockerfile используется только из Makefile (заполненного аргументами), когда мы запускаем make container . Давайте теперь обратимся в сам Makefile , Всё, что связано с docker , делает для нас именно он. 👇

Долгое время Make-файлы казались мне страшными (до этого я сталкивался с ними лишь при работе с кодом C ), но на самом деле ничего страшного здесь нет, и их много где можно использовать, в том числе для этого проекта! Посмотрим, какие цели у нас здесь есть в Makefile :

  • make test - первая в рабочем потоке - собранное приложение - создаёт исполняемый двоичный код в каталоге bin :
  • make test - тестовая - она снова использует почти тот же docker run , только здесь ещё есть скрипт test.sh (покажем только то, что нас интересует):

Эти строчки — важная часть файла. Первая из них собирает тестовые цели, где в качестве параметра указан путь. Вторая строчка запускает тесты и выводит документацию по тестированию ПО. Оставшиеся две строчки запускают gofmt и go vet . Они собирают и выводят ошибки (если таковые имеются).

  • make container - и, наконец, важнейшая часть - создание развёртываемого контейнера:

Код для этой цели довольно прост: сначала он подставляет переменные в in.Dockerfile , а затем запускает docker build для получения образа с "изменёнными" и "последними" тегами. И дальше передаёт имя контейнера на стандартный вывод.

  • Теперь, когда у нас есть образ, нужно где-то его хранить. С этим нам помогает make push , который помещает образ в хранилище образов Docker registry.
  • make ci - ещё один способ использовать Makefile — задействовать его в процессах непрерывной интеграции и развёртывания приложений (об этом речь пойдёт далее). Эта цель очень похожа на make test : тоже запускает все тесты и плюс к этому генерирует отчёты о покрытии, которые потом используются как вводная информация при проведении анализа кода.
  • make clean - и, наконец, если нам нужно провести очистку проекта, запускаем make clean , который удалит все файлы, сгенерированные предыдущими целями.

Остальные цели можно объединить в две группы: первые не так важны для нормального рабочего процесса, а вторые являются лишь частью других целей, поэтому о них можно не упоминать.

Завершаем статью важной частью — процессом непрерывной интеграции и развёртывания приложений. Не буду подробно расписывать, что в нем такого — вы и сами прекрасно сможете разобраться (практически в каждой строке есть комментарий, так что всё должно быть понятно):

Но кое-что можно прояснить.

В этой сборке Travis использована сборка Matrix Build с 4 параллельными заданиями для ускорения всего процесса:

  • Сборка и тестирование: здесь мы проверяем, что приложение работает как надо;
  • SonarCloud: здесь мы генерируем отчёты о покрытии и отправляем их на сервер SonarCloud;
  • CodeClimate: здесь — как и в предыдущем задании — мы генерируем отчёты о покрытии и отправляем их, только на этот раз в CodeClimate с помощью их генератора тестовых отчётов;
  • Push to Registry: и, наконец, помещаем наш контейнер в хранилище GitHub Registry.

Надеюсь, эта статья поможет вам в ваших будущих разработках кода на Go. Все подробности изложены в репозитории.

В следующей части узнаем, как на базе этого макета проекта, который мы сегодня выстроили, с лёгкостью создавать интерфейсы RESTful API, тестировать с базой данных в памяти, а также настраивать крутую документацию (а пока можно подсмотреть в ветке rest-api репозитория). 🙂

Читайте также: