Разбить проект в подпапки
Я хочу разбить свой проект на подпапки.
Я хочу эту структуру кода:
├── main.go
└── models
└── user.go
Где main.go находится:
package main
import (
"fmt"
"./models"
)
func main(){
fmt.Println(User{"new_user"})
}
И user.go - это:
package models
type User struct {
Login string
}
Но пользователь не определен в основном пакете, и предупреждение о повышении импорта "импортировано и не используется".
Что я делаю неправильно? Мой проект прост (не такой пример, но только с несколькими файлами (контроллеры и модели)), и я хочу простую структуру.
Может быть, я делаю это совершенно неправильно?
Проблемный проект находится здесь: https://github.com/abonec/go_import_problem
Ответы
Ответ 1
Недавно я достиг этого, используя модули go.
Golang представил предварительную поддержку opt-in для модулей начиная с версии v1.11.1, которая предназначена для полного устранения, откровенно говоря, абсурдной необходимости $GOPATH
. Теперь вы можете иметь не только версионные зависимости в любом обычном каталоге, например, ~/development
, но вы также можете иметь нечто похожее на пространства имен и подкаталоги. Вы можете включить эту функцию, вызвав команду go со следующей переменной среды: GO111MODULE=on
.
Go v1.11.3 предполагает включение модулей по умолчанию и запланирован на август 2019 года.
Вот пример структуры каталогов (которую вы можете найти обычно на некоторых других языках).
~/Dev/my-app
├── src/
│ ├── one/
│ │ ├── two/
│ │ │ └── two.go
│ │ └── one.go
│ └── zero.go
├── go.mod
└── app.go
Приложение называется my-app
, которое будет именем модуля для app.go
Мы определяем это один раз в go.mod
и тогда все остальные файлы go в подкаталогах будут автоматически импортироваться, как если бы они были пространством имен.
Учитывая вышесказанное, two.go
, предполагая, что он содержит функцию с именем Two
, будет импортирован в app.go
с помощью my-app/src/one/two
.
Вот что вам нужно сделать, чтобы добиться этого:
go.mod
module my-app
two.go
package two
func Two() string {
return "I'm totally not supposed to be using go modules for this"
}
app.go
package main
import "my-app/src/one/two"
func main() {
two.Two()
}
Если бы вы two.TheNewFunc()
другой файл в два /, то вы просто использовали бы two.TheNewFunc()
если вы сделали TheNewFunc()
доступным в новом файле.
Я создал очень простое GitHub репо, которое вы можете проверить в качестве демонстрации.
Ответ 2
Ваш импорт должен быть абсолютным:
import "github.com/abonec/go_import_problem/models"
Если вы не хотите экспортировать проект на внешний референт, вы можете сделать:
import "go_import_problem/models"
(То есть: "the name of your project folder accessible by GOPATH/your package
" )
См. "Как использовать пользовательские пакеты в golang?".
И вы бы использовали:
models.User
Как указано в Эффективный переход:
Импортер пакета будет использовать это имя для обозначения его содержимого, поэтому экспортированные имена в пакете могут использовать этот факт, чтобы избежать заикания.
( Не использовать нотацию .
импорта, что упростит тесты, которые должны выполняться за пределами тестируемого пакета, но в противном случае этого следует избегать.)
kostix добавляет в комментариях:
чтобы повторить, имена пакетов Go всегда абсолютные (то есть нет относительных имен пакетов, ни с ./
, ни с ../
, ни с чем-нибудь подобным), но , что имена "привязаны" к одной из так называемых рабочих областей, перечисленных в $GOPATH
.
Когда Go ищет пакет, он просматривает рабочие области и пытается найти пакет в каждом из них, в порядке.
Поиск не является рекурсивным. И нет, нет необходимости кодировать URL-адреса в пулах пакетов - если вы не хотите, чтобы ваш пакет был общедоступным.
Ответ 3
Вам нужно квалифицировать элементы в пакете по его имени пакета
So
fmt.Println(models.User{"new_user"})
Ответ 4
Разрыв одного проекта во вложенные папки не является рекомендуемым способом структурирования проекта go, поэтому в принципе нет хорошего способа сделать то, что вы хотите.
Если проект действительно большой и слишком громоздкий, чтобы сделать один пакет, рассмотрите его разделение на несколько совершенно разных пакетов, а не на специальные пакеты подкаталогов. Это имеет то преимущество, что заставляет вас думать о ваших внутренних API-интерфейсах.
Ответ 5
Пакеты упоминаются в коде относительно вашей папки "go/src"
└── go
└── src
└── myAwesomeProject
├── main.go
└── models
└── user.go
Так что в main.go
package main
import (
"fmt"
"myAwesomeProject/models"
)
Аналогично, пакеты могут ссылаться друг на друга, используя одно и то же соглашение.
Ответ 6
Вы должны использовать импортированные объекты импортированными именами. Например, если вы
import "./models"
со структурой Пользователь должен использовать его как
models.User