Есть ли способ запустить модуль Go из другого каталога

#go #gopath

#Вперед #gopath

Вопрос:

У меня есть следующая структура проекта, за пределами GOPATH .

 . // Project root
├── Dockerfile
├── .env
├── README.md
└── src
    ├── main.go
    ├── go.mod
    ├── go.sum
    ├── internal
    │   ├── somepackage
    │   │   ├── main.go
    │   │   └── types.go
    │   ├── someother
    │   │   ├── main.go
    │   │   ├── oauth.go
    │   │   └── types.go
    │   └── models
    │       └── main.go
    └── pkg
        ├── somepackage
        │   └── main.go
        └── anotherpackage
            └── main.go
  

Я хочу запустить свой код модуля Go, расположенный в src каталоге.
Когда я cd вхожу в src каталог и go run . / или go build . в свой код, он работает отлично.

Когда я стою в корне своего проекта, я не могу запустить go run ./src или go build ./src . Я получаю следующую ошибку.

 src/service.go:8:2: cannot find package "web-service/internal/auth" in any of:
        /usr/lib/go/src/web-service/internal/auth (from $GOROOT)
        /home/miloertas/Packages/go/src/web-service/internal/auth (from $GOPATH)
src/endpoints.go:3:8: cannot find package "web-service/internal/handlers" in any of:
        /usr/lib/go/src/web-service/internal/handlers (from $GOROOT)
        /home/miloertas/Packages/go/src/web-service/internal/handlers (from $GOPATH)
  

Важно, чтобы мой исходный код оставался в этом src каталоге.
Не менее важно, чтобы я мог run и build мой код из корня моего проекта (например .env , файл расположен в корне репозитория).

Поэтому я ищу способ run или build мой код в src каталоге из корня моего проекта.

Я попытался переместить go.mod в корень проекта и запустить и запустить go run ./src , но это вызывает собственные проблемы:

  • Теперь go команда не может найти все подпакеты в internal и pkg
  • VSCode теперь потерян, и выполнение тестов невозможно по некоторым причинам (в основном потому, что не найдены все подпакеты).

Комментарии:

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

2. Можно было бы ожидать, что что-то вроде go build ./src/... сработает, или что будет общий вариант, означающий «это корень проекта, где находится мой go.mod, работайте отсюда» , go build --root src ./... но, очевидно, я живу в стране фантазий. Возможно, вернитесь к старому доброму Makefile и закодируйте там свои цели и команды, завернутые в (cd src; go build ./...) .

Ответ №1:

Начиная с Go 1.18, теперь этого можно достичь с помощью рабочих пространств Go.

Используя следующую структуру каталогов

 parent-dir/
└─ go.work
   hello-world/
   ├─ go.mod
   └─ main.go
  

Вы можете запустить hello-world модуль из parent-dir using go run hello-world .

go.work

 go 1.18

use ./hello-world
  

go.mod

 module hello-world

go 1.18
  

Примечание: это возможно, но не рекомендуется, как указано @Volker

Ответ №2:

Важно, чтобы мой исходный код оставался в этом каталоге src. Не менее важно, чтобы я мог запускать и создавать свой код из корня моего проекта (например, файл .env расположен в корне репозитория).

Эти два требования противоречат друг другу. Вы должны отпустить его.

Особенно второй необоснованный: не используйте go run, используйте go build. Сделайте путь для поиска файла .env параметром командной строки для вашей программы (Go — это не PHP или JavaScript, просто нет проекта или исходного кода для исполняемого двоичного файла). Или создайте исполняемый файл где-нибудь, но запустите его в корне вашего проекта.

Обратите внимание, что наличие src папки, мягко говоря, необычно.

Я попытался переместить go.mod в корень проекта и запустить и запустить go run ./src, но это вызывает собственные проблемы:

Ну, начните с go run того, что вообще не используйте, используйте go build . А затем попробуйте создать фактический основной пакет. Все инструменты go лучше всего работают с пакетами, а не с папками файловой системы. Если ваш модуль назван playing.hardball/for-unspecific-reasons , а пакет main находится в src try go build playing.hardball/for-unspecific-reasons/src .

Выводы, даже если это работает не так, как вы хотите:

  • Не используйте go run . Причин много, полезно запускать однофайловые скрипты и загруженный footgun практически для любого другого варианта использования.
  • go Инструмент работает с путями импорта . В простых случаях путь импорта может быть выведен из файловой системы.
  • Скомпилированный исполняемый файл не имеет понятия «каталог проекта», «источник», «путь к классу» или что-то еще, это автономный исполняемый файл, который можно запускать везде и полностью отделен от его источников.
  • Сделайте весь путь поиска файловой системы параметром конфигурации (флаг командной строки или переменная среды); укажите практические значения по умолчанию (например ./ ); используйте это при запуске вашего исполняемого файла, чтобы сообщить, где найти статические вещи, такие как env-файлы, шаблоны, значки, css-файлы и т. Д.

Комментарии:

1. Я хотел узнать, возможно ли это, как в «Есть ли способ». Я знаю, что мой выбор дизайна очень необычен и не является «лучшей практикой», но это не моя точка зрения. В любом случае спасибо.

2. Хорошо: Нет, нет способа сделать это именно так, как вы хотите. Вы должны перепроектировать хотя бы некоторые аспекты вашего решения.

3. Хорошо, я думаю, что я собираюсь изменить свой макет. Спасибо. Я предлагаю вам указать, что это не может быть достигнуто в верхней части вашего ответа, чтобы избежать путаницы.

4. «Обратите внимание, что наличие папки src, мягко говоря, необычно». — вероятно, потому, что инструментарий go настолько упрям и негибок, что это практически невозможно, как обнаружил OP. Предлагаемый макет имеет смысл, если вы живете в разнородном мире многомодульной разработки.