Go Modules наступает на сводку ямы

Go

Общедоступная учетная запись WeChat «Back-end Advanced», ориентированная на совместное использование серверных технологий: Java, Golang, WEB-инфраструктура, распределенное промежуточное программное обеспечение, управление услугами и т. д.

В Java-проектах есть очень полезные инструменты управления версиями зависимостей, такие как Maven и Gradle. Это не слишком удобно, но в проектах Golang предыдущий официальный Golang не предоставлял инструментов управления версиями. Мы использовали go get, чтобы получить его. на самом деле потенциально опасны, потому что мы не уверены, нарушит ли последняя версия зависимости то, как наш проект использует пакет зависимостей, то есть текущий проект может быть несовместим с последним пакетом зависимостей. После этого был официально введен вендорский механизм, и пакеты, от которых зависел проект, были помещены в эту директорию, но это плохо управляло версиями зависимостей. После этого был официально выпущен квазиофициальный инструмент управления версиями go dep, который является предшественником модулей go. С выпуском Go1.11 Golang предоставил нам новые функции модуля, который представляет собой новый набор системы управления зависимостями в Golang. Теперь, когда выпущен Go1.12, модули go дополнительно стабилизированы, но официальный не установил его в качестве механизма по умолчанию, поэтому необходимо встать на путь.Помимо детализации характеристик и использования модулей go, это Статья также суммирует некоторые из «ям», с которыми я столкнулся в процессе.

Создать модуль

  • Создать проект

По умолчанию $GOPATH по умолчанию не поддерживает go Mudules, нам нужно вручную выполнить следующие команды в каталоге проекта:

$ export GO111MODULE=on

Это также показывает решимость go использовать механизм модулей для устранения $GOPATH!

Чтобы взаимодействовать с механизмом модулей go, мы создаем пакет testmod в каталоге, отличном от $GOPATH:

$ mkdir testmod
$ cd testmod

$ echo 'package testmod
		import "fmt"
	func SayHello(name string) string {
   return fmt.Sprintf("Hello, %s", name)
}' >> testmod.go
  • Инициализируйте модуль:
$ go mod init github.com/objcoding/testmod
go: creating new go.mod: module github.com/objcoding/testmod

Приведенная выше команда создаст в проекте файл go.mod со следующей инициализацией:

module github.com/objcoding/testmod

На данный момент наш проект стал модулем.

  • Отправить в репозиторий github
$ git init
$ git add *
$ git commit -am "First commit"
$ git push -u origin master

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

До появления go mudules в проекте было много пакетов.В проекте некоторые пакеты должны были зависеть от других пакетов в проекте.Предполагая, что в проекте есть пакет, адрес относительно gopath был objcoding/mypackage, а остальные пакеты в проекте, на который ссылается этот пакет, на него можно ссылаться следующим образом:

import myproject/mypackage

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

import github.com/objcoding/myproject/mypackage

После выпуска модулей go адрес ссылки на пакет полностью унифицируется.Как мы уже говорили выше, после создания файла go.mod первая строка содержимого инициализации — это то, что мы называем путем зависимости проекта.Вообще говоря, адрес — адрес склада проекта. , заполните этот адрес для всех адресов, которые должны ссылаться на пакет проекта, будь то внутренняя ссылка или внешняя ссылка, например, внутренняя ссылка на пакет goim:

модуль go.mod:

Внутренняя ссылка на пакет:

То есть после того, как в проекте включены модули Go, эталонный пакет должен быть таким же, как первая строка файлов Go MOD,

Зависимые пакеты будут сохранены в папке ${GOPATH}/pkg/mod, и мы также можем просмотреть зависимые пакеты в нижней части проекта:

Но также возможно, что адрес пакета зависимостей правильный, но он будет отмечен красным цветом.В настоящее время очень вероятно, что вы не установили проект в качестве проекта модулей go в редакторе Goland.Конкретные настройки следующие:

Когда этот параметр отмечен, каталог Go Modules появится во внешних библиотеках.

правило версии

Модули go – это система управления зависимостями с поддержкой версий. Версия должна соответствовать некоторым правилам. Например, номер версии должен соответствовать следующему формату:

vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
vX.0.0-yyyymmddhhmmss-abcdefabcdef
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
vX.Y.Z

vx.y.z - это версия нашей этикетки нашего склада, то есть модули GO определяет номер версии на основе метки склада, поэтому, когда мы выпустим версию, нам нужно метить наш склад с номером версии метки.

То есть номер версии + Timestamp + Hash. Когда мы указываем версию, нам нужно только указать номер версии. Если нет тега версий, нам нужно найти время и хеш-значение соответствующего коммита.

Еще одно важное правило заключается в том, что версии 0 и 1 желательно должны иметь разные пути зависимостей, например, v1.0.0 и v2.0.0 имеют разные пути зависимостей, правила версий будут подробно описаны ниже.

релизная версия

Разобравшись с правилами версий модулей go, теперь давайте выпустим версию проекта:

$ git tag v1.0.0
$ git push --tags

В настоящее время нам лучше создать ветку v1, чтобы мы могли писать код в других ветках, не затрагивая версию v1.0.0:

$ git checkout -b v1
$ git push -u origin v1

использовать модуль

Теперь мы берем модуль, который мы только что сделали, используем его и создаем новый проект gomodules:

package main

import (
    "fmt"
    "github.com/objcoding/testmod"
)

func main() {
    fmt.Println(testmod.SayHello("张乘辉"))
}

Раньше мы могли получить пакет зависимостей напрямую с помощью команды go get, но для модульного проекта это гораздо интереснее.Теперь инициализируем проект в модульный проект:

$ go mod init

В это время такие команды, как go build, загружают пакет зависимостей, добавляют информацию о зависимости в файл go.mod и сохраняют информацию о хэше версии зависимости в файле go.sum:

$ go build

go: finding github.com/objcoding/testmod v1.0.0
go: downloading github.com/objcoding/testmod v1.0.0

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

module gomodules
require github.com/objcoding/testmod v1.0.0

Содержимое файла go.sum следующее:

github.com/objcoding/testmod v1.0.0 h1:fGa15gBXoqkG0BVkQGP9i5Pg2nt8nayFpHFf+GLiX6A=
github.com/objcoding/testmod v1.0.0/go.mod h1:LGpYEmOLZhLQC3JW88STU2Ja3rsfoGZmsidsHJhDNGU=

Здесь также следует отметить, что иногда мы обращаемся к некоторым пакетам golang.org/x/, но обнаруживаем, что этот адрес — цянь на небесах, но наши программисты также в полной мере соблюдали прекрасную традицию быть прилежными и прилежными. Механизм goproxy задается в модулях.Если в модулях go установлен прокси, пакет зависимостей будет загружен сначала с прокси, а в /etc/profile будет добавлено следующее содержимое:

export GOPROXY="https://goproxy.io"

goproxy.io официальный прокси-адрес Google, и, конечно же, есть много отличных внутренних сторонних прокси.

Вы также можете установить в редакторе Goland:

обновленная версия

Теперь давайте обновим проект testmod:

$ cd gomodules
$ echo 'package testmod
		import "fmt"
	func SayHello(name string) string {
   return fmt.Sprintf("你好, %s", name)
}' >> testmod.go

Я изменил «Hello» на «Hello», давайте внесем это изменение в ветку v1:

$ git commit -m "update testmod" testmod.go
$ git tag v1.0.1
$ git push --tags origin v1

Теперь, когда наш проект был обновлен до версии 1.0.1, мы можем получить эту зависимость от версии разными способами.В go1.11 go get имеет много новых функций.Мы можем напрямую получить зависимость от версии 1.01 с помощью следующей команды :

$ go get github.com/objcoding/testmod@v1.0.1

Вы также можете использовать команду go mod:

$ go mod edit -require="github.com/objcoding/testmod@v1.0.1"

$ go mod tidy

go mod edit -require может активно изменять номер версии зависимостей в файле go.md, а потом обновлять версию через go mod tidy.Это богоподобная команда.Она автоматически подчистит ненужные зависимости, и при этом время, вы можете Зависимости обновляются до текущих версий.

Основная версия обновления

Приведенные выше правила версии говорят, что версии 0 и 1, то есть основные обновления версии, лучше всего иметь разные пути зависимостей, например: v1.0.0 и v2.0.0 имеют разные пути зависимостей, поэтому как использовать модули go для достижения Таким образом, мы можем добавить новые пути, изменив первую строку файла go.mod:

$ cd testmod
$ echo 'module github.com/objcoding/testmod/v2' >> go.mod

Затем мы модифицируем функцию testmod Hi():

$ cd testmod

$ echo 'package testmod
import (
	"fmt"
)
func SayHello(name, str string) string {
	return fmt.Sprintf("你好, %s, %s", name, str)
}' >> testmod.go

В настоящее время метод SayHello() не будет совместим с версией v1. Нам нужно создать новую версию v2.0.0. Она все та же. Нам лучше создать ветку v2 в версии v2.0.0 и напишите сюда код версии v2.0.0 В ветке (это просто спецификация, на самом деле вы тоже можете писать код в любой ветке, Go не имеет этой спецификации):

$ git add *
$ git checkout -b v2
$ git commit testmod.go -m "v2.0.0"
$ git tag v2.0.0
$ git push --tags origin v2

В настоящее время версия testmod была обновлена ​​до версии v2.0.0, которая несовместима с предыдущей версией, но текущий проект может получить только зависимую версию v1.0.1, потому что путь к модулю нашего testmod был добавлено с версией 2. Так что конфликта нет, так что, если нам нужно использовать версию v2.0.0? Нам просто нужно изменить путь импорта в проекте:

package main

import (
    "fmt"
  	"github.com/objcoding/testmod/v2"
)
func main() {
    fmt.Println(testmod.SayHello("张乘辉", "最近过得怎样"))
}

воплощать в жизнь:

go mod tidy

На данный момент мы обновили номер версии зависимости testmod до версии 2.0.0.Хотя путь импорта в настоящее время заканчивается на «v2», Go очень удобен для пользователя, и мы все еще можем использовать testmod для его использования.

公众号「后端进阶」,专注后端技术分享!