Как импортировать локальные пакеты без 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