Как использовать "внутренние" пакеты?

Я пытаюсь понять, как организовать код go, используя "внутренние" пакеты. Позвольте мне показать, какая у меня структура:

project/
  internal/
    foo/
      foo.go # package foo
    bar/
      bar.go # package bar
  main.go

# here is the code from main.go
package main

import (
  "project/internal/foo"
  "project/internal/bar"
)

project/ находится вне дерева GOPATH. Независимо от пути, который я пытаюсь импортировать из main.go ничего не работает, единственным main.go случаем является import "./internal/foo|bar". Я думаю, что я делаю что-то неправильно или вообще ошибаюсь в "внутренней" идее пакета. Может, кто-нибудь прояснит ситуацию, пожалуйста?

ОБНОВИТЬ

Приведенный выше пример правильный, единственное, что мне нужно, - это разместить project/ папку под $GOPATH/src. Итак, это путь импорта, так как project/internal/foo|bar работоспособна, если мы импортируем ее только из project/ поддерева, а не извне.

Ответ 1

Пакеты должны быть расположены в вашем $GOPATH для импорта. Пример, который вы import "./internal/foo|bar" с import "./internal/foo|bar" работает, потому что он выполняет локальный импорт. internal только делает его таким кодом, который не имеет общего корневого каталога во internal каталоге, не может импортировать пакеты внутри internal.

Если вы поместили все это в свой gopath, тогда попытались импортировать из другого места, такого как OuterFolder/project2/main.go где OuterFolder содержит как project и project2 тогда import "../../project/internal/foo" завершится неудачей. Он также потерпел бы неудачу в качестве import "foo" или любым другим способом, который вы попробовали из-за того, что он не удовлетворяет этому условию;

Импорт пути, содержащего элемент "internal", запрещен, если код импорта находится за пределами дерева, корневого в родительском "внутреннем" каталоге.

Теперь, если у вас есть путь $GOPATH/src/project вы можете import "foo" и import "bar" из $GOPATH/src/project/main.go и импорт будет успешным. Однако вещи, которые не содержатся под project, не смогут импортировать foo или bar.

Ответ 2

ниже способ более масштабируемый, особенно когда вы планируете построить несколько двоичных файлов

github.com/servi-io/api
├── cmd/
│   ├── servi/
│   │   ├── cmdupdate/
│   │   ├── cmdquery/
│   │   └── main.go
│   └── servid/
│       ├── routes/
│       │   └── handlers/
│       ├── tests/
│       └── main.go
├── internal/
│   ├── attachments/
│   ├── locations/
│   ├── orders/
│   │   ├── customers/
│   │   ├── items/
│   │   ├── tags/
│   │   └── orders.go
│   ├── registrations/
│   └── platform/
│       ├── crypto/
│       ├── mongo/
│       └── json/

Папки внутри cmd/ представляют количество двоичных файлов, которые вы хотите собрать.

для большего

Ответ 3

Когда вы создаете корень проекта, всегда лучше следовать $GOPATH/src/repo_url/username/project format ex: $GOPATH/src/github.com/apache/thrift


internal пакет

  • Если корневые пакеты вашего проекта хотят общаться друг с другом, перейдите к internal пакету
  • Если корневые пакеты вашего проекта только с использованием/импортом идут стандартными зависимостями или зависимостями поставщиков/третьих сторон не переходят на internal
  • Вещи внутри internal пакета нельзя импортировать из корневых пакетов проекта, кроме него внутри internal пакета, cmd или основного файла проекта main.go, который включает в себя основную функцию

Проекты, которые следуют за internal структурой пакета

Примечание: большинство библиотек go использовали эту internal упаковку

Подробнее: Примеры

Ответ 4

Также для проверки: когда вы используете свои внешние импортированные типы объектов: убедитесь, что вы ставите им префикс перед тем пространством имен, в котором они находятся. Как новичок в golang, я не знал, что должен был это сделать, и задавался вопросом, почему VS Код просто удаляет мой импорт (если он не используется), когда я сохраняю. Это потому, что мне пришлось префикс импортированного объекта с именем пространства имен:

Example:
import (
    "myInternalPackageName"  // works fine as long as you follow all instructions in this thread
)

//Usage in code: 
myInternalPackageName.TheStructName   // prefix it, or it won't work. 

Если вы не ставите префикс пространства имен перед именем объекта/структуры, код VS просто удаляет ваш импорт за то, что он не используется, а затем у вас по-прежнему возникает ошибка: "Не удается найти TheStructName"... Это очень сбивает с толку, и Я должен был сделать сборку без кода VS через командную строку, чтобы понять это.

Дело в том, что я должен был указать префикс пакета, когда фактически использовал структуру из этого внутреннего пакета.

Если вы не хотите использовать префикс квалификатора при использовании импортированных объектов, используйте:

import . "thePath"    // Can use contents without prefixing. 

Ссылка: Что означает "." (точка или точка) в операторе импорта Go?