При разработке базовой платформы или полагаться в процессор архитектуры характеристики GO Package, предоставляет соответствующую конкретную реализацию очень необходимо.
В Go нет предварительной обработки, нет системы определения макросов, и его нельзя использовать как язык C.#define
чтобы контролировать, включен ли код для конкретной платформы. Вместо этого Go используетпакет go/buildСистема маркировки, определенная в (system of tags
) и соглашения об именах (naming convention
)а такжеgo tool
Соответствующая поддержка, чтобы разрешить Go Go Packages для компиляции конкретного кода.
Эта статья объясняет условную компиляцию, как добиться, и как использовать его в своих собственных проектах.
во-первыхgo list
Прежде чем обсуждать условную компиляцию, нам нужно кратко обсудитьgo list
Заказ.go list
Позволяет получить доступ к структурам данных внутри пакета для управления процессом сборки.
go list
большинство параметров иgo build
,go test
,go install
То же самое, но он не выполняет компиляцию. использовать-f
Параметры форматирования, мы можем заполнить абзацtext/template
код шаблона, он будет в содержащемgo/build.PackageКонтекст структуры выполняется.
В следующем примере вы можете получить имена всех файлов исходного кода, которые будут скомпилированы.
% go list -f '{{.GoFiles}}' os/exec
[exec.go lp_unix.go]
Этот пример запрашивает мою текущую среду выполненияlinux/arm
Внизos/exec
Файлы в пакете, который будет скомпилирован. Есть два файла результатов:exec.go
содержит общий код, общий для всех платформ,lp_unix.go
содержитunix-like
уникальный для системыexec.LookPath
выполнить.
Если я выполню указанную выше команду в системе Windows, результат будет следующим:
C:\go> go list -f '{{.GoFiles}}' os/exec
[exec.go lp_windows.go]
Этот короткий пример демонстрирует систему условной компиляции Go, известную какОграничения сборки, о чем подробнее будет сказано далее.
Создать теги
Первый способ реализовать условную компиляцию — вставить в исходный код комментарии, называемые тегами сборки.
Комментарии для тегов сборки следует размещать как можно ближе к началу исходного файла.
Когда Go компилирует пакет, он анализирует каждый исходный файл в пакете и ищет теги сборки. Тег определяет, скомпилирован исходный файл или нет.
Вкладка Build следует трем принципам:
- Варианты, разделенные пробелом, представляют собой отношение ИЛИ (ИЛИ)
- Варианты, разделенные запятыми, - И (И)
- Каждый вариант состоит из букв и цифр. если ему предшествует
!
, значит наоборот
// +build darwin freebsd netbsd openbsd
В приведенном выше примере тег сборки появляется в верхней части исходного файла, указывая на то, что исходный файл будет поддерживать толькоkqueue
Скомпилировано на BSD-системах.
Исходный файл может содержать несколько тегов сборки. Правила сборки — это логика и взаимосвязь каждого отдельного правила. Следующий пример означает, что файл будет находиться вlinux/386
илиdarwin/386
платформа будет скомпилирована.
// +build linux darwin
// +build 386
Дополнительные примечания к примечаниям
Распространенная ошибка при первом использовании тегов сборки заключается в следующем:
// +build !linux
package mypkg // 错误
В этом примере между меткой сборки и объявлением пакета нет пустой строки. Это приводит к тому, что теги сборки игнорируются как описательная информация для объявлений пакетов. Правильный формат выглядит следующим образом:
// +build !linux
package mypkg // 正确
Примечание переводчика yoko, в исходном тексте здесь есть описание, что при выполнении go vet в правильном формате будет сообщено о следующей ошибке
+build comment appears too late in file
Я сделал простой тест, и выполнение go vet в правильном формате не сообщит об ошибке, наоборот, неправильный формат сообщит о следующей ошибке+build comment must appear before package clause and be followed by a blank line
Я думаю, это должна быть новая версия go to go ветеринар был улучшен, и среда, когда я тестировал ее, былаgo version go1.12.5 darwin/amd64
Вот пример, включающий лицензии, теги сборки и объявления пакетов:
% head headspin.go
// Copyright 2013 Way out enterprises. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build someos someotheros thirdos,!amd64
// Package headspin implements calculates numbers so large
// they will make your head spin.
package headspin
Суффиксы файлов
Второй метод условной компиляции — через имя исходного файла. Эта схема проще, чем построение схемы этикетки.
go/build
В документации к пакету есть описание соглашения об именах. Проще говоря, если имя файла содержит_$GOOS.go
суффикс, то файл исходного кода будет скомпилирован только на соответствующей платформе. Другие платформы игнорируют этот файл. Еще одна конвенция_$GOARCH.go
. Эти два суффикса можно комбинировать, но порядок гарантирован, правильный формат_$GOOS_$GOARCH.go
, неправильный формат_$GOARCH_$GOOS.go
.
Вот несколько примеров суффиксов имен файлов:
mypkg_freebsd_arm.go // 只在 freebsd/arm 系统编译
mypkg_plan9.go // 只在 plan9 编译
Недостаточно, чтобы исходный файл имел суффикс, например следующее имя файла:
_linux.go
_freebsd_386.go
Даже в системах Linux или FreeBSD эти два файла игнорируются, потому чтоgo/build
Пакет игнорирует все имена файлов, начинающиеся с.
и_
стартовый файл.
Используйте теги сборки или суффиксы имен файлов
Теги сборки и суффиксы имен файлов функционально перекрываются. Например, названныйmypkg_linux.go
Файл, а затем конструкция, содержащая метку// +build linux
Будет больше.
Вообще говоря, мы выбираем суффикс имени файла, когда необходимо указать только одну конкретную платформу или систему. Например:
mypkg_linux.go // 只在 linux 系统编译
mypkg_windows_amd64.go // 只在 windows amd 64位 平台编译
И наоборот, если ваш файл нужно указать для нескольких платформ или систем или вам нужно исключить конкретную платформу, мы выбираем способ построения тегов. Например:
// 在所有类unix平台编译
% grep '+build' $HOME/go/src/pkg/os/exec/lp_unix.go
// +build darwin dragonfly freebsd linux netbsd openbsd
// 在非Windows平台编译
% grep '+build' $HOME/go/src/pkg/os/types_notwin.go
// +build !windows
Суммировать
Эта статья посвящена только исходным файлам Go. Фактически, теги сборки и суффиксы имен файлов могут применяться к любому исходному файлу, который может скомпилировать инструмент go, включая.c
и.s
документ. В стандартной библиотеке GO, особенно в пакетах Runtime, Syscall, OS и NET, содержится большое количество этого примера.
Тестовые файлы также поддерживают теги сборки и суффиксов имени файла, которые ведут себя так же, как и исходные файлы. Это позволяет нам указывать определенные тестовые случаи для определенных платформ.
Наконец, в этой статье обсуждаетсяgo tool
, на самом деле функция условной компиляции не ограничивается этим инструментом. ты можешь пройтиgo/build
Пакет создает ваши собственные инструменты для анализа суффиксов имен файлов и создания синтаксиса тегов.
Эта статья переведена из книги Дэйва Чейни «Как использовать условную компиляцию с инструментом go build».Dave.Cheney.net/2013/10/12/…