11. go list и introspection проекта
Рентген вашего проекта
Если go env показывает глобальные настройки среды выполнения и тулчейна, то go list позволяет заглянуть внутрь структуры самого проекта. Это команда-инспектор, которая отвечает на ключевой вопрос компилятора: "Что Go реально видит в моих каталогах и файлах, прежде чем начнет строить бинарник?".
В классическом Unix-мире инженеры привыкли опрашивать файловую систему скриптами на базе find, grep и awk. Но в Go такой наивный подход быстро дает сбой: файл app_windows.go не должен компилироваться на Linux, файлы *_test.go не должны попадать в продакшн-сборку, а некоторые пакеты могут быть исключены из-за build-тегов //go:build. Для Senior-разработчика go list — это не просто способ узнать имена пакетов. Это фундаментальный инструмент интроспекции, анализа графа импортов и построения гибких Makefile и CI/CD пайплайнов.
JSON как API к тулчейну
Главная сила go list — возможность выводить информацию не плоским текстом, а в структурированном формате JSON (флаг -json). Это превращает утилиту в полноценное программное API к загрузчику пакетов (cmd/go/internal/load). Под капотом go list оперирует теми же структурами данных, что и компилятор, заполняя поля метаданными о файлах, импортах, зависимостях и ошибках.
Попробуйте выполнить в корне проекта:
go list -json ./...
Вы получите подробный массив данных. Вот как выглядит структура информации для каждого отдельного пакета:
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph Output ["Структура Package JSON"]
Dir["Dir: /path/to/project/pkg"]:::process
ImportPath["ImportPath: github.com/user/project/pkg"]:::entry
Name["Name: pkg"]:::process
GoFiles["GoFiles: .go файлы"]:::process
Imports["Imports: зависимости"]:::process
Deps["Deps: транзитивные зависимости"]:::process
end
subgraph Advanced ["Дополнительные поля"]
TestGoFiles["TestGoFiles: _test.go файлы"]:::process
XTestGoFiles["XTestGoFiles: внешние тесты"]:::process
Error["Error: ошибки компиляции"]:::error
end
Полезные флаги и шаблоны
Выводить полный JSON каждый раз избыточно. Для интеграции со скриптами автоматизации используется мощный механизм шаблонов Go (флаг -f), позволяющий извлекать конкретные поля структуры пакета.
1. Список всех зависимостей
Чтобы узнать, от каких пакетов зависит ваш проект (прямо или транзитивно):
go list -f '{{.Deps}}' ./...
2. Поиск main пакетов
Если у вас монорепозиторий с несколькими сервисами в каталоге cmd, вы можете программно найти все исполняемые точки входа:
# Найдет все пакеты с именем main
go list -f '{{if eq .Name "main"}}{{.ImportPath}}{{end}}' ./...
3. Файлы для компиляции
Иногда нужно передать список всех реальных .go файлов (исключая тесты) в кастомный линтер или анализатор:
go list -f '{{range .GoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}' ./...
Флаг -deps: Полный граф
Флаг -deps расширяет список выводимых пакетов. Без него go list ./... покажет только ваши локальные пакеты. С ним — вы получите дерево всех зависимостей, включая стандартную библиотеку и сторонние модули.
Это полезно для:
- Анализа "раздувания" бинарника (какие библиотеки тянутся).
- Поиска уязвимостей (проверка версий вложенных зависимостей).
- Визуализации графа зависимостей.
Кроме того, режим go list -m all опрашивает модули (а не пакеты), выводя полный список зафиксированных в go.mod внешних модулей с их точными версиями.
Работа с ошибками (-e)
Обычно, если пакет содержит синтаксические ошибки или сломанные зависимости, go list немедленно завершает работу с кодом ошибки. Но при построении диагностических инструментов и плагинов IDE нам критически важно получить метаданные обо всех корректных пакетах, даже если соседний пакет временно сломан. Флаг -e указывает команде игнорировать сбои и транслировать ошибки прямо в поле Error структуры JSON:
{
"ImportPath": "broken/pkg",
"Error": {
"ImportStack": ["broken/pkg"],
"Pos": "broken/pkg/main.go:5:2",
"Err": "undefined: someVar"
}
}
go list в Real World
Главный кейс использования — написание умных Makefile. Например, вы хотите запустить линтеры параллельно над всеми файлами, или сгенерировать документацию только для экспортируемых пакетов.
Пример скрипта для поиска всех go-файлов для статического анализатора:
FILES=$(go list -f '{{range .GoFiles}}{{$.Dir}}/{{.}} {{end}}' ./...)
my-custom-tool $FILES
Также именно go list используется редакторами кода (VSCode, GoLand) и сервером языка gopls для формирования списка файлов, отображения структуры проекта и навигации. Если ваш проект странно ведет себя в IDE, иногда помогает ручной запуск go list -e -json ./... чтобы увидеть, не отвалился ли какой-то пакет из-за ошибок сборки.
Итог
go list— это API для интроспекции проекта через консоль.- Формат вывода
-jsonидеален для парсинга скриптами и CI. - Шаблоны
-fпозволяют фильтровать данные прямо на этапе запроса. - Флаг
-depsпоказывает полное дерево зависимостей. - Используйте этот инструмент для автоматизации рутины (поиск файлов, пакетов).
Мы научились "рентгенить" структуру проекта. Теперь пора углубиться в то, как эта структура связана с внешним миром — зависимостями. В следующей статье мы разберем фундамент современной Go-разработки: 12. Модули. go.mod и go.sum.