пятница, 5 июля 2019 г.

Вспомогательные темы инструмента go: протокол прокси модуля

go help goproxy

Команда go по умолчанию загружает модули из систем управления версиями напрямую, как это всегда бывает с go get. Переменная среды GOPROXY позволяет дополнительно контролировать источник загрузки. Если GOPROXY не установлен, является пустой строкой или строкой "direct", при загрузке используется прямое подключение по умолчанию к системам контроля версий. Отключение GOPROXY запрещает загрузку модулей из любого источника. В противном случае ожидается, что GOPROXY будет URL-адресом прокси модуля, и в этом случае команда go извлечет все модули из этого прокси. Независимо от источника модулей, загруженные модули должны соответствовать существующим записям в go.sum.

Прокси модуля Go - это любой веб-сервер, который может отвечать на запросы GET для URL-адресов заданной формы. Запросы не имеют параметров запроса, поэтому даже сайт, обслуживающий фиксированную файловую систему (включая file:/// URL), может быть прокси модуля.

GET-запросы, отправленные на прокси Go модуля:

GET $GOPROXY/<module>/@v/list возвращает список всех известных версий данного модуля, по одной на строку.

GET $GOPROXY/<module>/@v/<version>.info возвращает метаданные в формате JSON об этой версии данного модуля.

GET $GOPROXY/<module>/@v/<version>.mod возвращает файл go.mod для этой версии данного модуля.

GET $GOPROXY/<module>/@v/<version>.zip возвращает zip-архив для этой версии данного модуля.

Чтобы избежать проблем при обслуживании из файловых систем с учетом регистра, элементы <module> и <version> кодируются регистром, заменяя каждую заглавную букву восклицательным знаком, за которым следует соответствующая строчная буква: github.com/Azure кодируется как github.com/!azure.

Метаданные в формате JSON о данном модуле соответствуют этой структуре данных Go, которая может быть расширена в будущем:

type Info struct {
    Version string    // строка версии
    Time    time.Time // время комита
}

Zip-архив для конкретной версии данного модуля - это стандартный zip-файл, содержащий дерево файлов, соответствующее исходному коду модуля и связанным файлам. В архиве используются разделенные косой чертой пути, и каждый путь к файлу в архиве должен начинаться с <module>@<version>/, где модуль и версия подставляются напрямую, а не в регистре. Корень дерева файлов модулей соответствует префиксу <module>@<version>/ в архиве.

Даже при загрузке непосредственно из систем управления версиями команда go синтезирует явно info, mod и zip файлы и сохраняет их в своем локальном кэше, $GOPATH/pkg/mod/cache/download, так же, как если бы она загружала их непосредственно из прокси. Макет кэша такой же, как и у прокси-пространства URL, поэтому обслуживание $GOPATH/pkg/mod/cache/download в (или копирование его) https://example.com/proxy позволит другим пользователям получать доступ к этим версиям кэшированных модулей с GOPROXY=https://example.com/proxy.


Читайте также:


четверг, 4 июля 2019 г.

Каталоги поставщиков (Vendor Directories) в Golang

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

Код под каталогом с именем vendor импортируется только кодом в дереве каталогов, корнем которого является родительский элемент vendor, и только с использованием пути импорта, в котором префикс не указан, вплоть до элемента vendor.

Вот пример из предыдущего поста, но с "internal" каталогом, переименованным в "vendor" и добавленным новым каталогом foo/vendor/crash/bang:

/home/user/go/
    src/
        crash/
            bang/              (go код в пакете bang)
                b.go
        foo/                   (go код в пакете foo)
            f.go
            bar/               (go код в пакете bar)
                x.go
            vendor/
                crash/
                    bang/      (go код в пакете bang)
                        b.go
                baz/           (go код в пакете baz)
                    z.go
            quux/              (go код в пакете main)
                y.go

Применяются те же правила видимости, что и для internal, но код в z.go импортируется как "baz", а не как "foo/vendor/baz".

Код в vendor каталогах, находящихся глубже в дереве исходного кода затеняет код в вышестоящих каталогах. В поддереве с корнем в foo импорт "crash/bang" разрешается в "foo/vendor/crash/bang", а не в "crash/bang" верхнего уровня.

Код в каталогах поставщиков не подлежит проверке пути импорта (см. go help importpath).

Когда 'go get' проверяет или обновляет git-репозиторий, теперь он также обновляет подмодули.

Каталоги поставщиков не влияют на размещение новых репозиториев, впервые проверяемых с помощью функции 'go get': они всегда помещаются в основной GOPATH, а не в поддерево поставщиков.


Читайте также:


GOPATH и модули в Golang, внутренние каталоги

При использовании модулей GOPATH больше не используется для разрешения импорта. Однако он все еще используется для хранения загруженного исходного кода (в GOPATH/pkg/mod) и скомпилированных команд (в GOPATH/bin).

Внутренние каталоги

Код внутри или ниже каталога с именем "internal" импортируется только кодом в дереве каталогов, корнем которого является родительский элемент "internal". Вот расширенная версия макета каталога из поста:

/home/user/go/
    src/
        crash/
            bang/              (go код в пакете bang)
                b.go
        foo/                   (go код в пакете foo)
            f.go
            bar/               (go код в пакете bar)
                x.go
            internal/
                baz/           (go код в пакете baz)
                    z.go
            quux/              (go код в пакете main)
                y.go

Код в z.go импортируется как "foo/internal/baz", но этот оператор импорта может появляться только в исходных файлах в поддереве с корнем в foo. Исходные файлы foo/f.go, foo/bar/x.go и foo/quux/y.go могут импортировать "foo/internal/baz", но исходный файл crash/bang/b.go не может.


Читайте также:


Установка переменной среды GOPATH

Переменная среды GOPATH указывает местоположение вашего рабочего пространства. Если GOPATH не задан, предполагается, что он равен $HOME/go в системах Unix и %USERPROFILE%\go в Windows. Если вы хотите использовать пользовательское местоположение в качестве своего рабочего пространства, вы можете установить переменную среды GOPATH. В этом посте объясняется, как установить эту переменную на разных платформах.

Unix системы

GOPATH может быть любым каталогом в вашей системе. В примерах Unix мы установим его в $HOME/go (по умолчанию начиная с Go 1.8). Обратите внимание, что GOPATH не должен совпадать с вашей установкой Go. Другой распространенной настройкой является установка GOPATH=$HOME.

Bash

Отредактируйте ваш ~/.bash_profile, добавив следующую строку:

export GOPATH=$HOME/go

Сохраните и выйдите из редактора. Затем отправьте ваш ~/.bash_profile как источник.

source ~/.bash_profile

Zsh

Отредактируйте файл ~/.zshrc, добавив следующую строку:

export GOPATH=$HOME/go

Сохраните и выйдите из редактора. Затем отправьте ваш ~/.zshrc как источник.

source ~/.zshrc

fish

set -x -U GOPATH $HOME/go

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

Windows

Ваше рабочее пространство может быть расположено где угодно, но в этом примере мы будем использовать C:\go-work.

ПРИМЕЧАНИЕ. GOPATH не должен совпадать с вашей установкой Go.

  • Создайте папку в C:\go-work.
  • Щелкните правой кнопкой мыши на «Пуск» и нажмите «Панель управления». Выберите «Система и безопасность», затем нажмите «Система».
  • В меню слева выберите «Расширенные настройки системы».
  • Нажмите кнопку «Переменные среды» внизу.
  • Нажмите «Создать» в разделе «Пользовательские переменные».
  • Введите GOPATH в поле «Имя переменной».
  • Введите C:\go-work в поле «Значение переменной».
  • Нажмите ОК.

Windows 10

Существует более быстрый способ редактирования переменных среды с помощью поиска:

  • Щелкните левой кнопкой мыши на «Поиск» и введите env или environment.
  • Выберите «Изменить переменные среды для вашей учетной записи».
  • ... и следуйте инструкциям выше.

Windows 10 (cli версия)

  • Откройте командную строку (windows-key + r, затем введите «cmd») или окно powershell(windows-key + i)
  • Введите setx GOPATH %USERPROFILE%\go (это установит GOPATH в вашу [домашняя папка]\go, например, C:\Users\yourusername\go
  • Закройте окно командной строки или powershell (переменная среды доступна только для новых командных строк или окон powershell, но не для текущего окна).

Читайте также:


Вспомогательные темы инструмента go: переменная среды GOPATH

go help gopath

Путь Go (Go path) используется для разрешения операторов импорта. Он реализован и задокументирован в пакете go/build.

Переменная окружения GOPATH перечисляет места для поиска кода Go. В Unix значение представляет собой строку, разделенную двоеточиями. В Windows значение представляет собой строку, разделенную точкой с запятой.

Если переменная среды не установлена, GOPATH по умолчанию использует подкаталог с именем "go" в домашнем каталоге пользователя ($HOME/go в Unix, %USERPROFILE%\go в Windows), если только этот каталог не содержит дистрибутив Go. Запустите "go env GOPATH", чтобы увидеть текущую GOPATH.

Смотрите этот пост, чтобы установить пользовательскую GOPATH.

Каждый каталог, указанный в GOPATH, должен иметь предписанную структуру:

Каталог src содержит исходный код. Путь ниже src определяет путь импорта или имя исполняемого файла.

В каталоге pkg хранятся установленные объекты пакета. Как и в дереве Go, каждая целевая пара операционной системы и архитектуры имеет свой собственный подкаталог pkg (pkg/GOOS_GOARCH).

Если DIR является каталогом, указанным в GOPATH, пакет с источником в DIR/src/foo/bar можно импортировать как "foo/bar", а его скомпилированная форма установлена в "DIR/pkg/GOOS_GOARCH/foo/bar.a".

Каталог bin содержит скомпилированные команды. Каждая команда названа для своего исходного каталога, но только конечный элемент, а не весь путь. То есть команда с источником в DIR/src/foo/quux устанавливается в DIR/bin/quux, а не в DIR/bin/foo/quux. Префикс "foo/" удален, так что вы можете добавить DIR/bin в PATH, чтобы получить доступ к установленным командам. Если установлена переменная среды GOBIN, команды устанавливаются в каталог, который она называет, а не в DIR/bin. GOBIN должен быть абсолютным путем.

Вот пример макета каталога:

GOPATH=/home/user/go

/home/user/go/
    src/
        foo/
            bar/               (go код в пакете bar)
                x.go
            quux/              (go код в пакете main)
                y.go
    bin/
        quux                   (установленная команда)
    pkg/
        linux_amd64/
            foo/
                bar.a          (установленный объект пакета)

Go ищет каждый каталог, указанный в GOPATH, чтобы найти исходный код, но новые пакеты всегда загружаются в первый каталог в списке.

См. этот пост для примера.


Читайте также:


Вспомогательные темы инструмента go: файл go.mod

go help go.mod

Версия модуля определяется деревом исходных файлов с файлом go.mod в его корне. Когда команда go выполняется, она просматривает текущий каталог, а затем последующие родительские каталоги, чтобы найти go.mod, отмечающий корень основного (текущего) модуля.

Сам файл go.mod ориентирован на строки, с // комментариями, но без /* */ комментариев. Каждая строка содержит одну директиву, состоящую из глагола, за которым следуют аргументы. Например:

module my/thing
go 1.12
require other/thing v1.0.2
require new/thing/v2 v2.3.4
exclude old/thing v1.2.3
replace bad/thing v1.4.5 => good/thing v1.4.5

Глаголы:

module  чтобы определить путь модуля;
go      чтобы установить ожидаемую версию языка;
require требовать определенный модуль в данной версии 
        или новее;
exclude чтобы исключить конкретную версию модуля 
        из использования;
replace чтобы заменить версию модуля другой 
        версией модуля.

exclude и replace применяются только в go.mod основного модуля и игнорируются в зависимостях.

Ведущий глагол может быть выделен из соседних строк для создания блока, как в импорте Go:

require (
    new/thing v2.3.4
    old/thing v1.2.3
)

Файл go.mod предназначен как для непосредственного редактирования, так и для удобного обновления инструментами. Команда go mod edit может использоваться для анализа и редактирования файла go.mod из программ и инструментов.

Команда go автоматически обновляет go.mod каждый раз, когда использует граф модуля, чтобы go.mod всегда точно отражал реальность и был правильно отформатирован. Например, рассмотрим этот файл go.mod:

module M

require (
        A v1
        B v1.0.0
        C v1.0.0
        D v1.2.3
        E dev
)

exclude D v1.2.3

Обновление переписывает неканонические идентификаторы версий в форму semver, поэтому версия v1 для A становится v1.0.0, а dev для E становится псевдо-версией для последнего коммита в ветви dev, возможно, v0.0.0-20180523231146-b3f5c0f6e5f1.

Обновление изменяет требования для соблюдения исключений, поэтому требование исключенной версии D v1.2.3 обновляется для использования следующей доступной версии D, возможно, версии D v1.2.2 или D v1.3.3.

Обновление устраняет избыточные или вводящие в заблуждение требования. Например, если для A v1.0.0 требуется B v1.2.0 и C v1.0.0, то требование go.mod для B v1.0.0 вводит в заблуждение (заменено потребностью A в v1.2.0) и требованием C v1.0.0 является избыточным (подразумевается потребность A в одной и той же версии), поэтому оба будут удалены. Если модуль M содержит пакеты, которые напрямую импортируют пакеты из B или C, то требования будут сохранены, но обновлены до фактических используемых версий.

Наконец, обновление переформатирует go.mod в каноническое форматирование, так что будущие механические изменения приведут к минимальным различиям.

Поскольку граф модуля определяет значение операторов импорта, любые команды, которые загружают пакеты, также используют и, следовательно, обновляют go.mod, включая go build, go get, go install, go list, go test, go mod graph, go mod tidy и go mod why.


Читайте также:


Вспомогательные темы инструмента go: типы файлов

go help filetype

Команда go проверяет содержимое ограниченного набора файлов в каждом каталоге. Она определяет, какие файлы проверять, основываясь на расширении имени файла. Эти расширения:

.go
    Go исходные файлы.
.c, .h
    C исходные файлы.
    Если пакет использует cgo или SWIG, 
    они будут скомпилированы с OS-native компилятором 
    (обычно gcc); в противном случае 
    они будут вызывать ошибку.
.cc, .cpp, .cxx, .hh, .hpp, .hxx
    C++ исходные файлы. Полезно только с cgo или SWIG, 
    и всегда скомпилированы OS-native компилятором.
.m
    Objective-C исходные файлы. Полезно только с cgo,
    и всегда скомпилированы OS-native компилятором.
.s, .S
    Исходные файлы ассемблера.
    Если пакет использует cgo или SWIG, они будут 
    собраны с OS-native ассемблером (обычно gcc (sic)); 
    в противном случае они будут собраны с ассемблером Go.
.swig, .swigcxx
    SWIG файлы определения.
.syso
    Системные объектные файлы.

Файлы каждого из этих типов, кроме .syso, могут содержать ограничения компоновки, но команда go прекращает поиск ограничений компоновки для первого элемента в файле, который не является пустой строкой или комментарием строки в стиле //.

В версии Go 1.12 исходные файлы Go, не входящие в тест, также могут включать комментарий //go: binary-only-package, указывающий, что источники пакета включены только для документации и не должны использоваться для сборки бинарного файла пакета. Это позволяет распространять пакеты Go только в скомпилированном виде. Даже бинарные пакеты требуют точных блоков импорта, перечисляющих требуемые зависимости, так что эти зависимости могут быть предоставлены при связывании результирующей команды. Обратите внимание, что эту функцию планируется удалить после выпуска Go 1.12.


Читайте также:


купить игрушку gopher