- PVSM.RU - https://www.pvsm.ru -
Скоро выходит версия Go 1.18, и в массовом сознании она, скорее всего, будет ассоциироваться с Generic-ами. Но помимо них туда попадает еще несколько вкусных фичей. Например, Go Workspaces [1].
Go Workspaces позволяет работать одновременно с несколькими модулями. Теоретически это можно было делать и раньше, но Go Workspaces добавляет немного комфорта.
Ранее при работе с несколькими модулями одновременно их нужно было «связать» через директиву replace
в go.mod
-файле.
Подход с replace-ами в go.mod
имеет ряд существенных недостатков:
каждый модуль живёт своей независимой жизнью и некоторый инструментарий разработки умеет одновременно работать только с одним модулем.
replace
-ы не транзитивны. То есть если вы добавляете в go.mod
новый replace
, то его надо добавить во все использующие его модули. Даже при небольшом количестве модулей это доставляет заметные неудобства.
запустить утилиту через go run
можно только из каталогов тех модулей, которые либо содержат эту утилиту, либо «видят» её через replace (при этом она еще должна быть объявлена как require
).
Go Workspaces добавляет немного комфорта:
gopls
предоставляет информацию сразу по всем используемым модулям;
общие replace
-ы можно описать в одном месте, и они видны для всех объявленных модулей;
локальные правки с директивой replace
не нужно прописывать внутри go.mod
файлов, которые лежат в репозитории;
сборка и запуск утилит для всех объявленных модулей может быть из каталога, в котором лежит go.work
и его дочерних каталогов;
добавляется команда go work sync
, которая позволяет обновить зависимости нескольких модулей до наиболее свежей общей версии.
При использовании go.work
-файла Go собирает общий список зависимостей из всех перечисленных в go.mod
-файлов, с учетом replace
-директив. На базе всех перечисленных зависимостей формируется единый граф зависимостей, который и применяется ко всем используемым модулям. Если для одного модуля указано в разных go.mod
несколько конфликтующих replace
-директив — будет ошибка.
К примеру, если один модуль требует зависимость на github.com/davecgh/go-spew [2] версии v1.1.1
, а другой модуль требует зависимость на github.com/davecgh/go-spew [2] версии v1.1.0
, то оба модуля будут исполняться с более старшей версией v1.1.1
.
Это работает для всех модулей одного Go Workspace, даже если между модулями нет зависимости.
Если вы хотите использовать несколько go.mod
-файлов в рамках одного (моно)репозитория, то go.work
вам никак в этом не поможет: в рамках одного Go Workspace используются общие зависимости, собранные на основе всех используемых go.mod
-файлов. То есть такой подход ничем принципиально не будет отличаться от использования одного go.mod
-файла, кроме увеличения сложности за счет большего количества используемых файлов.
Собственно ссылка на соседние модули через тэги или идентификатор коммита также остаются за кадром Go Workspace.
Для использования Go Workspaces добавилась группа команд go work
.
Для начала нужно вызвать команду go work init
в корне рабочего пространства.
Допустим у нас есть рабочее пространство вида:
shared
— с модулем из пакета github.com/bozaro/go/go-work-play/shared [3]
tools
— с модулем из пакета github.com/bozaro/go/go-work-play/tools [4]
Тогда для использования Go Workspaces надо:
Создать go.work
файл:
go work init
Добавить туда модули:
go work use shared
go work use tools
В итоге создастся файл go.work
с содержимым вида:
go 1.18
use (
shared
tools
)
И далее, к примеру, можно вызвать сборку из любого подкаталога внутри рабочего пространства:
go run github.com/bozaro/go/go-work-play/tools/hello
Если в go.work
добавить replace
-ы, то они так же будут иметь эффект на все модули рабочего пространства.
Важно понимать, что использование Go Workspaces меняет поведение некоторых команд, например:
go run
перестаёт работать для модулей, которые не объявлены в go.work
;
go list
не может менять go.mod
файлы:
go list -mod=mod -m -json
go: -mod may only be set to readonly when in workspace mode, but it is set to "mod"
Remove the -mod flag to use the default readonly value,
or set -workfile=off to disable workspace mode.
К этому изменению некоторые утилиты могут быть не готовы.
Я для себя сделал следующие выводы.
Использование Go Workspaces сильно упрощает выполнение каких-либо утилит за счет возможности вызова их из любого места рабочего пространства без лишних приседаний.
Можно не добавлять паразитные replace
директивы в go.mod
файлы для того, чтобы править одновременно несколько связанных проектов.
При использовании go.work
можно получить ситуацию, запускаемый код будет выполняться не с теми зависимостями, которые указаны в go.mod
файле, и об этом нужно помнить. К счастью, зависимости можно свести через команду go work sync
.
Проблема с несколькими go.mod
в рамках одного репозитория с помощью Go Workspaces не решается никак.
Автор: Артем Навроцкий
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/golang/372234
Ссылки в тексте:
[1] Go Workspaces: https://go.googlesource.com/proposal/+/master/design/45713-workspace.md
[2] github.com/davecgh/go-spew: http://github.com/davecgh/go-spew
[3] github.com/bozaro/go/go-work-play/shared: http://github.com/bozaro/go/go-work-play/shared
[4] github.com/bozaro/go/go-work-play/tools: http://github.com/bozaro/go/go-work-play/tools
[5] Источник: https://habr.com/ru/post/652103/?utm_source=habrahabr&utm_medium=rss&utm_campaign=652103
Нажмите здесь для печати.