Как импортировать локальные пакеты без gopath
Я использовал GOPATH
, но для этой текущей проблемы, с которой я столкнулся, это не помогает. Я хочу иметь возможность создавать пакеты, специфичные для проекта:
myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go
Я пробовал несколько способов, но как мне получить package1.go
для работы в binary1.go
или binary2.go
и т.д.?
Например; Я хочу иметь возможность import "package1"
, а затем иметь возможность запускать go build binary1.go
, и все работает отлично, не вызывая ошибки, что пакет не может быть найден на GOROOT
или GOPATH
. Причина, по которой мне нужна такая функциональность, - это крупномасштабные проекты; Я не хочу ссылаться на несколько других пакетов или хранить их в одном большом файле.
Ответы
Ответ 1
Перейти к сводке управления зависимостями:
vgo
, если ваша версия go: x >= go 1.11
dep
или vendor
, если ваша версия go: go 1.6 >= x < go 1.11
- Вручную, если ваша версия go:
x < go 1.6
Редактировать 3: Go 1.11 имеет функцию vgo
, которая заменит dep
.
Чтобы использовать vgo
, см. документацию Модули. TLDR ниже:
export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build
Этот метод создает файл с именем go.mod
в каталоге ваших проектов. Затем вы можете построить свой проект с помощью go build
. Если установлено GO111MODULE=auto
, то ваш проект не может быть в $GOPATH
.
Изменить 2: метод вендора все еще действителен и работает без проблем. vendor
является в основном ручным процессом, из-за этого были созданы dep
и vgo
.
Изменить 1: Хотя мой старый способ работает, это уже не "правильный" способ сделать это. Вы должны использовать возможности vendor, vgo
или dep
(на данный момент), которые по умолчанию включены в Go 1.6; см. Вы в основном добавляете свои "внешние" или "зависимые" пакеты в каталог vendor
; после компиляции компилятор сначала будет использовать эти пакеты.
Нашел. Я смог импортировать локальный пакет с помощью GOPATH
, создав подпапку package1
, а затем импортировав с помощью import "./package1"
в сценарии binary1.go
и binary2.go
, например:
binary1.go
...
import (
"./package1"
)
...
Итак, моя текущая структура каталогов выглядит следующим образом:
myproject/
├── binary1.go
├── binary2.go
├── package1/
│ └── package1.go
└── package2.go
Я также должен отметить, что относительные пути (по крайней мере, в версии 1.5) также работают; например:
import "../packageX"
Ответ 2
Нет такой вещи, как "локальный пакет". Организация пакетов на диске ортогонально любым родительским/дочерним отношениям пакетов. Единственной реальной иерархией, образованной пакетами, является дерево зависимостей, которое в общем случае не отражает дерево каталогов.
Просто используйте
import "myproject/packageN"
и не бороться с системой сборки без уважительной причины. Сохранение дюжины символов для импорта в любой нетривиальной программе не является веской причиной, потому что, например, проекты с относительными путями импорта не являются go-gettable.
Концепция путей импорта имеет некоторые важные свойства:
- Пути импорта могут быть глобально уникальными.
- В сочетании с GOPATH путь импорта может быть однозначно переведен в путь к каталогу.
- Любой путь к каталогу в GOPATH может быть однозначно переведен на путь импорта.
Все вышесказанное разрушено с помощью относительных путей импорта. Не делайте этого.
PS: В устаревшем коде в тестах компилятора Go используются несколько мест, которые используют относительный импорт. ATM, это единственная причина, по которой относительный импорт поддерживается вообще.
Ответ 3
Возможно, вы пытаетесь модулировать свой пакет. Я предполагаю, что package1
и package2
являются, в некотором роде, частью одного и того же пакета, но для удобства чтения вы разделяете их на несколько файлов.
Если предыдущий случай был вашим, вы могли бы использовать одно и то же имя пакета в этих файлах с множественными значениями, и это будет похоже на то, был ли тот же файл.
Это пример:
add.go
package math
func add(n1, n2 int) int {
return n1 + n2
}
subtract.go
package math
func subtract(n1, n2 int) int {
return n1 - n2
}
donothing.go
package math
func donothing(n1, n2 int) int {
s := add(n1, n2)
s = subtract(n1, n2)
return s
}
Я не эксперт Go, и это мой первый пост в StackOveflow, поэтому, если у вас есть какой-то совет, он будет хорошо принят.
Ответ 4
У меня похожая проблема, и для решения, которое я сейчас использую, используются модули Go 1.11. У меня есть следующая структура
- projects
- go.mod
- go.sum
- project1
- main.go
- project2
- main.go
- package1
- lib.go
- package2
- lib.go
И я могу импортировать package1 и package2 из project1 и project2 с помощью
import (
"projects/package1"
"projects/package2"
)
После запуска go mod init projects
. Я могу использовать go build
из каталогов project1 и project2 или я могу сделать go build -o project1/exe project1/*.go
из каталога проектов.
Недостатком этого метода является то, что все ваши проекты имеют общий список зависимостей в go.mod. Я все еще ищу решение этой проблемы, но похоже, что оно может быть фундаментальным.
Ответ 5
Чтобы добавить в проект "локальный" пакет, добавьте папку (например, "имя_пакета" ). И поместите свои файлы реализации в эту папку.
src/github.com/GithubUser/myproject/
├── main.go
└───package_name
└── whatever_name1.go
└── whatever_name2.go
В вашем package main
сделайте следующее:
import "github.com/GithubUser/myproject/package_name"
Где package_name
- имя папки, и оно должно совпадать с именем пакета, используемым в файлах any_name1.go и what_name2.go. Другими словами, все файлы с подкаталогом должны иметь один и тот же пакет.
Вы можете дополнительно вложить больше подкаталогов, пока вы укажете весь путь к родительской папке в импорте.
Ответ 6
Если вы находитесь в операционной системе * nix, такой как OS X или Linux, вы можете использовать символическую ссылку, чтобы иметь лучшее из обоих миров с реальным $GOPATH, которое позволяет вам go get
библиотеки и структуру проекта, которая не имеет жить в $GOPATH.
ln -s ~/path/to/myproject/ $GOPATH/src/myproject
Затем вы можете легко импортировать свои библиотеки, выполнив следующие действия:
import "myproject/mylib"
Конечно, это начинает разрушаться, если ваш проект становится больше, у вас есть много других разработчиков, изменяющих код, или публично публикую свой код и т.д. Но для небольших проектов с одним разработчиком это работает как альтернатива в:
- Чтобы нажать на публичное репо и
import "github.com/user/myprojcet/mylib"
везде
- Наличие постоянной обезьяны с вашим $GOPATH