Как использовать "внутренние" пакеты?
Я пытаюсь понять, как организовать код 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?