Как мне структурировать модуль Go, чтобы можно было легко запускать его и импортировать внутренние пакеты? - PullRequest
0 голосов
/ 08 июля 2019

Я просто открываю для себя Го.Когда я начал просматривать его на прошлой неделе, я узнал, что GOPATH и как Go, по-видимому, очень самоуверен в том, в каких каталогах вы храните свой код. Поэтому я проклял имя Google и решил, что Go не для меня, а затем недавно услышал о модулях Go икак, по-видимому, они решают эту самую проблему.

Проблема в том, что информация в Интернете о том, как структурировать Go-проект на основе модулей, кажется очень скудной.У меня проблемы с выяснением того, как выложить мой код и как вызывать пакеты, чтобы заставить импорт работать.Я пробовал разные вещи и смотрел примеры, но независимо от того, что я делаю, я получаю ошибки «неизвестный путь импорта».

В основном я хочу иметь каталог, скажем, с main.go и library.go, может быть, с library.go в подкаталоге.Я хочу иметь возможность писать import library или что-то подобное в main.go и иметь доступ к членам library.go.Я также хочу иметь возможность запустить код, набрав go run main.go.Это достижимо?

1 Ответ

1 голос
/ 08 июля 2019

Это сбивает с толку, и документация предполагает уровень знакомства с Голангом. Я пытался понять Модули недавно. Я надеюсь, что следующее поможет.

С наилучшими пожеланиями, изучая Голанг.

Предыдущий | текущий путь без модулей:

WORKDIR=[[PATH-TO-YOUR-WORKING-DIRECTORY]]

mkdir -p ${WORKDIR}/go
export GOPATH=${WORKDIR}/go
export PATH=${GOPATH}/bin:${PATH}

mkdir -p {${WORKDIR}/go/src/foo, ${WORKDIR}/go/src/foo/bar}

Затем создайте ${WORKDIR}/go/src/foo/bar/library.go:

package bar

func Something() (string) {
    return "Hello Freddie"
}

Затем создайте ${WORKDIR}/go/src/foo/main.go:

package main

import (
    "fmt"
    "foo/bar"
)

func main() {
    fmt.Printf("%s", bar.Something())
}

У вас будет такая структура:

.
└── go
    └── src
        └── foo
            ├── bar
            │   └── library.go
            └── main.go

Тогда вы можете запустить это одним из следующих способов:

GO111MODULE=off go run ${WORKDIR}/go/src/main.go
Hello Freddie!

cd ${WORKDIR}/go/src/
GO111MODULE=off go run main.go
Hello Freddie!

GO111MODULE=off go run foo
Hello Freddie!

Новый (!) Способ с модулями:

Предполагая, что вы сделали выше!

Вам не нужно делать этот шаг, но это новая лучшая практика. Мы перемещаем наши источники за пределы ${GOPATH}. ${GOPATH} все еще используется для хранения наших версионных пакетов. NB В этом тривиальном примере мы не используем внешние пакеты, поэтому ${GOPATH} остается пустым.

mv ${WORKDIR}/go/src/foo ${WORKDIR}
rm ${WORKDIR}/go/src

Вы должны иметь такую ​​структуру:

.
├── foo
│   ├── bar
│   │   └── library.go
│   └── main.go
└── go

NB Наши источники теперь находятся за пределами ${GOPATH}

cd ${WORKDIR}/foo

GO111MODULE=on go mod init foo
more go.mod
module foo

go 1.12

GO111MODULE=on go run foo
Hello Freddie!

GO111MODULE=on go run main.go
Hello Freddie!

Для полноты

Чтобы показать разницу с внешними пакетами:

No Modules загружает последнюю версию пакета в ${GOPATH}/src:

GO111MODULE=off go get github.com/golang/glog

.
├── foo
│   ├── bar
│   │   └── library.go
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── go
    └── src
        └── github.com
            └── golang
                └── glog
                    ├── glog_file.go
                    ├── glog.go
                    ├── glog_test.go
                    ├── LICENSE
                    └── README

По сравнению с использованием модулей, перетаскивает определенную версию (или версии) пакета в ${GOPATH}/pkg:

GO111MODULE=on go get github.com/golang/glog

.
├── foo
│   ├── bar
│   │   └── library.go
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── go
    └── pkg
        ├── linux_amd64
        │   └── github.com
        │       └── golang
        │           └── glog.a
        └── mod
            ├── cache
            │   ├── download
            │   │   └── github.com
            │   │       └── golang
            │   │           └── glog
            └── github.com
                └── golang
                    └── glog@v0.0.0-20160126235308-23def4e6c14b
                        ├── glog_file.go
                        ├── glog.go
                        ├── glog_test.go
                        ├── LICENSE
                        └── README

Примечания

  • Наши имена файлов несколько произвольны. Вы сказали library.go, поэтому я использовал это, и условно, файлы названы в соответствии с их содержанием.
  • Наши имена каталогов важны. Go использует имена каталогов, чтобы помочь найти пакеты. Поэтому, хотя library.go можно было бы назвать freddie.go или something.go, важно, чтобы оно было package bar и находилось в каталоге с именем bar.
  • Исключением из этих правил является то, что main.go обычно там, где определено func main() {...}, а func main() {...} должно находиться в пакете с именем main. Таким образом, даже если каталог называется foo, так как нам нужна функция main, мы назовем файл main.go, и он должен быть package main.
  • В пакете bar важно, чтобы Something был заглавным (S). Это экспортирует функцию из пакета bar, чтобы ее могли использовать другие пакеты. Если имя функции было в нижнем регистре (something), функция доступна только для других функций в пакете bar.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...