Перейти к основному содержимому
Модуль 9 · Урок 5 из 545/50 в курсе~10 min
Уроки модуля (5/5)

Создание ограничений и тегов

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

Современный синтаксис: //go:build.

Начиная с Go 1.17+, каноническим форматом является специальный комментарий //go:build, размещаемый в верхней части файла перед package, на отдельной строке, за которой следует пустая строка:

Go
//go:build linux

package main

// this file is built ONLY on Linux

Три абсолютных правила:

  1. Комментарий должен появиться перед package.
  2. За ним должна следовать пустая строка.
  3. Между // и go:build нет пробела (это синтаксический триггер, а не просто комментарий).

Логические выражения

Выражение после //go:build допускает логические операторы:

Go
//go:build linux && amd64           // both conditions
//go:build linux || darwin          // any one (Unix-like)
//go:build !windows                 // negation
//go:build (linux || darwin) && !arm64
//go:build go1.22                   // Go version ≥ 1.22
//go:build integration              // custom tag (see below)

Наиболее распространенные встроенные теги:

  • ОС: linux, darwin, windows, freebsd, js...
  • Архитектура: amd64, arm64, 386, wasm...
  • Версия Go: go1.20, go1.22... (истина, если версия ≥).
  • cgo: true, если cgo включен.

Кроссплатформенность: соглашение об именах файлов

Помимо явных тегов, Go распознает суффиксы имен файлов как неявные ограничения сборки:

Code
db_linux.go         // linux only
db_windows.go       // windows only
db_linux_amd64.go   // linux/amd64 only

Это идиоматический шаблон для платформозависимых реализаций одного и того же интерфейса (каждый файл определяет одни и те же функции с разным кодом).

Пользовательские теги: выбор в пользу тяжелых тестов

Пользовательские теги – это любой идентификатор, который вы передаёте в командной строке:

Go
//go:build integration

package mypkg

// tests that need a real DB, run only on demand

Исполнение:

Bash
go test -tags=integration ./...

Без -tags=integration файл невидим для компилятора (тесты внутри него не существуют для go test). Это канонический способ отделить модульные тесты (всегда) от интеграционных тестов (по требованию, возможно, только в CI).

Старый синтаксис: // +build (устаревший)

До версии 1.17 формат был // +build linux (обратите внимание на пробел и на то, что это +build, а не go:build). Он по-прежнему поддерживается для обратной совместимости, но gofmt в Go 1.17+ добавляет оба, когда находит только старый:

Go
//go:build linux
// +build linux

package main

Для новых файлов используйте только современную форму //go:build.

Упражнения

Упражнение#go.m9.l5.e1
Попыток: 0Загрузка…

Вверху файла добавьте ограничение сборки, которое компилирует его ТОЛЬКО в Linux. Помните пустую строку перед пакетом.

Загрузка редактора…
Показать подсказку

Комментарий //go:build идет ПЕРЕД пакетом на отдельной строке, за которой следует пустая строка.

Решение доступно после 3 попыток

Упражнение#go.m9.l5.e2
Попыток: 0Загрузка…

Добавьте ограничение сборки, ИСКЛЮЧАЮЩЕЕ Windows (используйте оператор отрицания!).

Загрузка редактора…

Решение доступно после 3 попыток

Quiz#go.m9.l5.e3
Готово

Какой флаг вы используете, чтобы включить во время тестирования специальный тег интеграции, объявленный с помощью интеграции //go:build?

Go
$ go test -tags=???
Варианты ответа