Go get не может найти локальные пакеты при использовании модулей

У меня проблемы с новой модульной системой, так как я хочу определить локальный модуль и импортировать его в основную программу. Локальный пакет находится в папке основной папки пакета/корня. Представьте себе следующую структуру проекта за пределами $GOPATH.

Структура проекта

./main.go

package main

import "fmt"
import "example.com/localModule/model"

func main() {
    var p = model.Person{name: "Dieter", age:25}
    fmt.Printf("Hello %s\n", p.name)
}

./model/person.go

package model

type Person struct {
    name string
    age int
}

В корневой папке я инициализировал модуль, вызывая

go mod init example.com/localModule

В model/ папке я затем инициализировал подмодуль, вызывая

go mod init example.com/localModule/model

Ошибка

В корневой папке вызывается вызов следующих команд.

$ go get
go build example.com/localModule/model: no Go files in

$ go build
main.go:4:8: unknown import path "example.com/localModule/model": cannot find module providing package example.com/localModule/model

Сообщение об ошибке для go get отключено, я не ошибаюсь.

Я не планирую нажимать модуль на сервер и просто нужен способ ссылки на локальную model пакета, поэтому я выбрал example.com/localModule/ и example.com/localModule/model соответственно.

Я использую go1.11 darwin/amd64 на Macbook с MacOS 10.13.6.

Ответ 1

У вас могут быть локальные "под" модули, как вы просите, добавив инструкцию require и соответствующий оператор replace с относительным пути к файлу в go.mod.

В "root"./go.mod:

module example.com/localModule

require example.com/localModule/model v0.0.0

replace example.com/localModule/model v0.0.0 => ./model

Ответ 2

Udated:

см. ответ Йостайна Стюхауга

Ответ 3

Причина, по которой вы получаете эту ошибку, заключается в том, что вы определили два модуля, которые не знают, как найти друг друга на локальном диске.

$ go build
main.go:4:8: unknown import path "example.com/localModule/model": 
 cannot find module providing package example.com/localModule/model

Хотя можно использовать директиву replace чтобы один модуль мог найти другой модуль на диске, гораздо более распространенным и простым решением является:

  • Иметь один файл go.mod в вашем хранилище, и
  • Поместите этот единственный файл go.mod в корень вашего хранилища.

Это очень простое решение, и оно означает, что ваши два пакета в репозитории смогут находить друг друга, что позволяет избежать сообщения об ошибке, о котором вы сообщили, а также избежать необходимости в директиве replace здесь.

Расс Кокс прокомментировал в # 26664:

Для всех, кроме опытных пользователей, вы, вероятно, захотите принять обычное соглашение, что один репо = один модуль. Для долгосрочного развития вариантов хранения кода важно, чтобы хранилище могло содержать несколько модулей, но это почти наверняка не то, что вы хотите сделать по умолчанию.

Если вместо этого вы хотите, чтобы в одном репозитории было определено несколько модулей, есть немало нюансов о том, как это сделать правильно, и есть целый раздел вики-модулей по тому, как управлять сложностью, связанной с несколькими модулями в Единый репозиторий, включая этот совет:

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

а также

Пожалуйста, внимательно прочитайте все часто задаваемые вопросы в этом подразделе, если вы планируете иметь несколько модулей в одном репозитории.