Как писать go-пакеты
Содержание:
- Сборка бинарных файлов Go с помощью команды go build
- Step 1 — Setting Up Go
- Limitations
- Formatting Imports
- Tutorial Series
- Testing your Go installation with the Hello World program
- Артефакты чрезмерной простоты
- GOPATH и модули
- Шаг 2 — Создание рабочего пространства Go
- Настройка переменной среды $GOPATH
- Step 6 — Creating a Simple Program
- The deprecated -r flag
- Заключение
Сборка бинарных файлов Go с помощью команды go build
Используя , вы можете сгенерировать исполняемый бинарный файл для нашего примера приложения Go, позволяющего распределять и развертывать программу, где захотите.
Попробуйте сделать это с . В директории запустите следующую команду:
Если вы не предоставите аргумент этой команде, будет автоматически компилировать программу в текущем каталоге. Команда будет использовать все файлы в директории. Также она выполнит сборку всего вспомогательного кода, необходимого для исполнения бинарного файла на любом компьютере с той же системной архитектурой, независимо от того, есть ли в системе исходные файлы или даже установка Go.
В данном случае вы создали приложение в исполняемом файле, добавленном в текущую директорию. Проверьте это, запустив команду :
Если вы используете macOS или Linux, то найдете новый исполняемый файл, который назван по директории, где вы выполнили сборку вашей программы:
Примечание. В Windows ваш исполняемый файл будет называться .
По умолчанию будет генерировать исполняемый файл для текущей . Например, при сборке в системе исполняемый файл будет совместимым с любой другой системой , даже если там не установлен Go. Go поддерживает сборку для других платформ и архитектур, о чем вы можете узнать подробнее из нашей статьи Сборка приложений Go для разных операционных систем и архитектур.
Теперь, когда вы создали исполняемый файл, запустите его, чтобы убедиться, что бинарный файл сформирован корректно. В macOS или Linux запустите следующую команду:
В Windows запустите следующую команду:
Вывод бинарного файла будет соответствовать выводу, когда вы запустили программу с командой :
Теперь вы создали один исполняемый бинарный файл, который содержит не только вашу программу, но и весь системный код, необходимый для запуска этого бинарного файла. Теперь вы можете распространить данную программу на новые системы или развернуть ее на сервере, зная, что файл всегда будет запускать ту же программу.
В следующем разделе настоящего руководства вы узнаете, как присваивается имя бинарного файла и как вы можете его изменить, чтобы лучше контролировать процесс сборки вашей программы.
Step 1 — Setting Up Go
In this step, you’ll install Go by downloading the current release from the official Go downloads page.
To do this, you’ll want to find the URL for the current binary release tarball. You will also want to note the SHA256 hash listed next to it, as you’ll use this hash to verify the downloaded file.
You’ll be completing the installation and setup on the command line, which is a non-graphical way to interact with your computer. That is, instead of clicking on buttons, you’ll be typing in text and receiving feedback from your computer through text as well.
The command line, also known as a shell or terminal, can help you modify and automate many of the tasks you do on a computer every day, and is an essential tool for software developers. There are many terminal commands to learn that can enable you to do more powerful things. For more information about the command line, check out the Introduction to the Linux Terminal tutorial.
On Ubuntu 18.04, you can find the Terminal application by clicking on the Ubuntu icon in the upper-left hand corner of your screen and typing into the search bar. Click on the Terminal application icon to open it. Alternatively, you can hit the , , and keys on your keyboard at the same time to open the Terminal application automatically.
Once the terminal is open, you will manually install the Go binaries. While you could use a package manager, such as , walking through the manual installation steps will help you understand any configuration changes to your system that are needed to have a valid Go workspace.
Before downloading Go, make sure that you are in the home () directory:
Use to retrieve the tarball URL that you copied from the official Go downloads page:
Next, use to verify the tarball:
The hash that is displayed from running the above command should match the hash that was on the downloads page. If it does not, then this is not a valid file and you should download the file again.
Next, extract the downloaded archive and install it to the desired location on the system. It’s considered best practice to keep it under :
You will now have a directory called in the directory. Next, recursively change this directory’s owner and group to root:
This will secure all the files and ensure that only the root user can run the Go binaries.
Note: Although is the officially-recommended location, some users may prefer or require different paths.
In this step, you downloaded and installed Go on your Ubuntu 18.04 machine. In the next step you will configure your Go workspace.
Limitations
As mentioned above, the go command is not a general-purpose build
tool.
In particular, it does not have any facility for generating Go
source files during a build, although it does provide
,
which can automate the creation of Go files before the build.
For more advanced build setups, you may need to write a
makefile (or a configuration file for the build tool of your choice)
to run whatever tool creates the Go files and then check those generated source files
into your repository. This is more work for you, the package author,
but it is significantly less work for your users, who can use
«» without needing to obtain and build
any additional tools.
Formatting Imports
By formatting imports, you can sort the packages into a specific order that will make your code more consistent. Additionally, this will prevent random commits from taking place when the only thing that changes is the sort order of the imports. Since formatting imports will prevent random commits, this will prevent unnecessary code churn and confusing code reviews.
Most editors will format imports for you automatically, or will let you configure your editor to use . It is considered standard practice to use in your editor, as trying to manually maintain the sort order of your imports can be tedious and prone to errors. Additionally, if any style changes are made, will be updated to reflect those style changes. This ensures that you, and anyone that works on your code, will have consistent styling in your import blocks.
Here is what an example import block may look like before formatting:
Running the tool (or with most editors that have it installed, saving the file will run it for you), you will now have the following format:
Notice that it groups all standard library packages first and then groups third party packages together with blank lines. This makes is easier to read and understand what packages are being used.
In this section we learned that using will keep all of our import blocks properly formatted, and prevent unnecessary code churn between developers working on the same files.
Tutorial Series
How To Install and Set Up a Local Programming Environment for Go
This tutorial series will guide you through installing Go on your local machine and setting up a programming environment via the command line. Go is a programming language that was designed for fast compilation, ease of programming, and efficient execution in production.
Next in series: How To Write Your First Program in Go
How To Code in Go
Go (or GoLang) is a modern programming language originally developed by Google that uses high-level syntax similar to scripting languages. It is popular for its minimal syntax and innovative handling of concurrency, as well as for the tools it provides for building native binaries on foreign platforms.
Next in series: How To Write Your First Program in Go
Testing your Go installation with the Hello World program
First, make sure that you have created the Go workspace directory at . Next, create a new directory inside your workspace. Finally, create a file named with the following code —
The easiest way to run the above program is using the command —
Building an executable binary using
The command compiles and runs your program at one go. If however, you want to produce a binary from your Go source that can be run as a standalone executable without using the Go tool, then use the command —
The command creates an executable binary with the same name as the name of your immediate package (). You can run the binary file like so —
Installing the package into the directory using
You can use the command to build and install the executable binary into your workspace’s directory —
You can also add the directory to the variable to run go executables from any location.
Don’t forget to check out: , , .
Артефакты чрезмерной простоты
Быть простым — это достойное стремление в любом дизайне, а попытаться сделать нечто простым трудно. Однако при попытке решить (или даже выразить) сложные задачи, порой необходим сложный инструмент. Сложность и запутанность не лучшие черты языка программирования, но существует золотая середина, при которой в языке возможно создание элегантных абстракций, простых в понимании и использовании.
Не очень выразительный
Из-за стремления к простоте в Go отсутствуют конструкции, которые в остальных языках воспринимаются как что-то естественное. Вначале это может показаться хорошей идеей, но на практике выходит многословный код. Причина этому должна быть очевидна — необходимо, чтобы разработчикам было просто читать чужой код, но на самом деле эти упрощения только вредят читаемости. Сокращения в Go отсутствует: либо много, либо ничего.
К примеру, консольная утилита, которая читает stdin либо файл из аргументов командной строки, будет выглядеть следующим образом:
Хотя и этот код пытается быть как можно более общим, принудительная многословность Go мешает, и в результате решение простой задачи выливается в большой объем кода.
Вот, к примеру, решение той же задачи на D:
И кто теперь более читабельный? Я отдам свой голос D. Его код куда более читаемый, так как он более явно описывает действия. В D используются концепции куда сложнее (прим.пер.: альтернативный вызов функций и шаблоны), чем в примере с Go, но на самом деле нет ничего сложного в том, чтобы разобраться в них.
Ад копирования
Популярное предложение для улучшения Go — это обобщенность. Это хотя бы поможет избежать ненужного копирования кода для поддержки всех типов данных. К примеру, функцию для суммирования списка целых чисел можно реализовать никак иначе, кроме как ее копипастой ее базовой функции для каждого целого типа, другого способа нет:
И этот пример даже не работает для знаковых типов. Такой подход полностью нарушает принцип не повторять себя (DRY), один из наиболее известных и очевидных принципов, игнорирование которого является источником многих ошибок. Зачем Go это делает? Это ужасный аспект языка.
Тот же пример на D:
Простое, элегантное и прямо в точку. Здесь используется функция для шаблонного типа и предиката. Да, это опять же сложнее варианта с Go, но не столь уж сложно для понимания умными программистами. Который из примеров проще поддерживать и легче читать?
Простой обход системы типов
Я полагаю, читая это, программисты Go будут с пеной во рту кричать: «Ты делаешь это не так!». Что же, есть еще один способ сделать обобщенную функцию и типы, но это полностью разрушает систему типов!
Взгляните на этот пример глупого исправления языка для обхода проблемы:
Эта имплементация была позаимствована из статьи Idiomatic generics in Go (прим.пер.: перевод не нашел, буду рад, если поможете с этим). Что же, если это идиоматично, я бы не хотел увидеть не идиоматичный пример. Использование — фарс, и в языке он нужен лишь для обхода типизации. Это пустой интерфейс и все типы его реализуют, позволяя полную свободу для всех. Этот стиль программирования до ужаса безобразен, и это еще не все. Для подобных акробатических трюков требуется использовать рефлексию времени выполнения. Даже Робу Пайку не нравятся индивиды, злоупотребляющие этим, о чем он упоминал в одном из своих докладов.
Я бы взял шаблоны D вместо этой чепухи. Как кто-то может сказать, что более читаем или даже типобезопасен?
GOPATH и модули
Казалось бы, в этом месте надо кинуться устанавливать , но я не буду этого делать. На самом деле уже и так задан:
Меня устраивает вариант с в , а значит, менять его я не буду.
Я сразу создам директорию для своего первого проекта на Go. Это можно сделать в любом месте, например, прямо в домашнем каталоге. Также я сразу начну работать с инструментом Go Modules:
Для команды я указала уникальный путь модуля моего проекта. По этому пути прокси или другой инструмент в случае необходимости сможет найти файлы моего проекта.
После вызова команды в моем домашнем каталоге появилась директория :
При этом lock-файл (в самом низу дерева), пока пуст.
В каталоге появился файл со следующим содержанием:
Именно в впоследствии будет храниться вся информация о зависимостях моего модуля.
Давайте теперь напишем приложение, использующее внешнюю зависимость. В директории я создаю файл и пишу в него такой код:
Конечно, в реальной жизни для написания «Hello, world!» можно обойтись и без logrus, но в этом примере эта библиотека поможет нам узнать, где хранятся файлы внешних зависимостей.
Запускаю приложение самым простым способом:
Перед тем, как приложение было собрано и запущено, сработал инструмент . Он определил мою внешнюю зависимость , взял ее последнюю на данный момент версию и отправился за транзитивными зависимостями.
В файл добавилась строка с описанием зависимости от :
Также появился файл , в котором помимо хэша зависимости хранится информация о хэшах транзитивных зависимостей:
Где же сам код зависимостей? Его можно найти в . Также, в будут храниться контрольные суммы и другая служебная информация для работы с зависимостями.
Если вы уже сталкивались с инструментом , знаете, что он при вытягивании зависимостей фактически клонирует репозитории (например, в случае git с помощью ). Но работает не так. Для основная единица кода — модуль. Модули представляют собой архивы. Во время работы с зависимостями явно (если вы вызывали команду ) или неявно (если вы запустили компиляцию приложения) скачивает и распаковывает архивы через . Давайте посмотрим, как прокси задан в Go 1.13 по умолчанию:
Итак, в качестве прокси при сборке моего «Hello, World!» использовался proxy.golang.org. Конечно, эту переменную можно изменить, выбрав другое хранилище модулей. Например, можно развернуть свой собственный внутренний прокси компании, где будут храниться, в том числе, внутренние библиотеки, код которых не публиковался в open source.
В общем, если я начинаю новый проект и не против использования Go Modules, мне можно ничего не знать о . Go самостоятельно создаст директорию тогда, когда это будет нужно.
Шаг 2 — Создание рабочего пространства Go
После установки Go вы можете создать рабочее пространство для программирования. На корневом уровне рабочего пространства Go имеются две директории:
- : это директория с исходными файлами Go. Исходный файл или файл исходного кода — это файл, который вы пишете на языке программирования Go. Компилятор Go использует исходные файлы для создания исполняемого двоичного файла.
- : директория, содержащая исполняемые файлы, которые были созданы и установлены инструментами Go. Исполняемые файлы — это двоичные файлы, которые запускаются в системе и выполняют задачи. Обычно это программы, скомпилированные из вашего исходного кода или из другого загруженного исходного кода Go.
Субдиректория может содержать несколько репозиториев контроля версий (например, Git, Mercurial и Bazaar). Это обеспечивает канонический импорт кода в ваш проект. Канонический импорт — это операция импорта, которая ссылается на полностью квалифицированный пакет, например .
При импорте сторонних двоичных файлов вашей программой вы увидите директорию , или другую директорию, откуда ваша программа импортирует сторонние библиотеки. Если вы используете репозиторий кода, например , вы также помещаете в эту директорию свои проекты и файлы исходного кода. Мы изучим эту концепцию на следующем шаге.
Вот так выглядит типичное рабочее пространство:
Директория по умолчанию рабочего пространства Go в версии 1.8 совпадает с домашней директорией вашего пользователя с субдиректорией или имеет адрес . Если вы используете версию Go ниже 1.8, лучше всего использовать для рабочего пространства адрес .
Введите следующую команду для создания структуры директорий рабочего пространства Go:
Опция предписывает команде создать в директории все , даже если их еще не существует. При использовании параметров для команды создается набор аргументов, предписывающий ей создать директорию и директорию .
Таким образом, обеспечивается размещение следующей структуры директорий:
До выпуска версии Go 1.8 обязательно было создавать локальную переменную среды с именем . указывает компилятору, где находится импортированный сторонний исходный код, а также написанный вами локальный исходный код. Хотя это больше явно не требуется, создать такую переменную все равно полезно, поскольку многие сторонние инструменты зависят от ее использования.
Вы можете задать , добавив глобальные переменные в ваш . Также вы можете добавить ее в файл или в соответствии с конфигурацией оболочки.
Откройте файл с помощью или другого предпочитаемого текстового редактора:
Чтобы задать переменную , добавьте в файл следующую строку:
~/.profile
При компиляции и установке инструментов Go помещает их в директорию . Для удобства субдиректория рабочего пространства обычно добавляется в переменную в файле :
~/.profile
Это позволит запускать любые компилируемые или загружаемые программы через инструменты Go в любом месте в вашей системе.
Наконец, вам нужно добавить двоичный файл в . Для этого добавьте в конец строки:
~/.profile
Добавление в переменную делает все инструменты Go доступными в любом месте в вашей системе.
Чтобы обновить оболочку, запустите следующую команду для загрузки глобальных переменных:
Вы можете проверить обновление переменной , запустив команду и просмотрев результаты:
Вы увидите директорию в своей домашней директории. Если вы вошли в систему с именем пользователя , вы увидите в составе пути.
Также вы увидите путь к инструментам Go для :
Для проверки установки проверьте текущую версию Go:
Результат должен выглядеть следующим образом:
Вы создали корневую директорию рабочего пространства и задали переменную среды . Теперь вы сможете создавать будущие проекты со следующей структурой директорий. В этом примере предполагается, что вы используете в качестве репозитория:
Например, если вы работаете над проектом , он будет сохранен в следующей директории:
При такой структуре проекты доступны с помощью инструмента . Также она делает проекты удобнее для чтения. Для проверки вы можете использовать команду для доставки библиотеки :
При этом будет загружено содержимое библиотеки , и на компьютере будет создана директория .
Можно проверить успешную загрузку пакета посредством вывода директории:
Результат должен выглядеть примерно следующим образом:
На этом шаге вы создали рабочее пространство Go и настроили необходимые переменные среды. На следующем шаге мы протестируем рабочее пространство, запустив в нем код.
Настройка переменной среды $GOPATH
Переменная среды $GOPATH перечисляет места, где Go ищет рабочие пространства.
По умолчанию Go предполагает, что расположение GOPATH находится в $HOME/go, где $HOME – корневой каталог учетной записи пользователя на компьютере. Это можно изменить, установив переменную окружения $GOPATH. Более подробно эти механизмы описаны в мануале Чтение и установка переменных среды и оболочки на сервере Linux.
Для получения дополнительной информации о настройке переменной $GOPATH читайте .
- Установка Go и настройка локальной среды разработки в macOS
- Установка Go и настройка локальной среды разработки в Ubuntu 18.04
Step 6 — Creating a Simple Program
Now that you have your Go workspace set up, it’s time to create a simple “Hello, World!” program. This will make sure that your workspace is working and gives you the opportunity to become more familiar with Go.
Because you are creating a single Go source file, and not an actual project, you don’t need to be in your workspace to do this.
From your home directory, open up a command-line text editor, such as , and create a new file:
Once the text file opens up in Terminal, type out your program:
Exit nano by typing the and keys, and when prompted to save the file press .
This code will use the package and call the function with as the argument. This will cause the phrase to print out to the terminal when the program is run.
Once you exit out of and return to your shell, run the program:
The program that you just created will cause Terminal to produce the following output:
In this step, you used a basic program to verify that your Go workspace is properly configured.
The deprecated -r flag
For older versions of Go, the flag tells save to automatically rewrite
package import paths. This allows your code to refer directly to the copied
dependencies in . So, a package C that depends on package
D will actually import . This makes C’s repo
self-contained and causes to build C with the right version of all
dependencies.
If you don’t use , when using older version of Go, then in order to use the
fixed dependencies and get reproducible builds, you must make sure that every
time you run a Go-related command, you wrap it in one of these two ways:
-
If the command you are running is just , run it as , e.g.
- When using a different command, set your using as
described below.
isn’t necessary with go1.6+ and isn’t allowed.
Заключение
Статья кому-то может показаться сложноватой, но это из-за того, что я попытался объяснить многое разом. Реальность же такова, что модули Go сегодня в целом просты — мы, как обычно, импортируем пакет в наш код, а остальное за нас делает команда . Зависимости при сборке загружаются автоматически.
Модули также избавляют от необходимости в , которая была камнем преткновения для новых разработчиков Go, у кого были проблемы с пониманием, почему надо что-то положить в какой-то конкретный каталог.
Вендоринг (неофициально) объявлен устаревшим в пользу использования прокси.
Я могу сделать отдельную статью про прокси для Go модулей.
Примечания:
1 Я думаю, что это слишком громкое выражение и у некоторых может остаться впечатление, что вендоринг убирают прямо сейчас. Это не так. Вендоринг все ещё работает, хотя и слегка по другому, чем раньше. По-видимому, есть желание заменить вендоринг чем-то лучшим, например, прокси (не факт). Пока это просто стремление к лучшему решению. Вендоринг не уйдет, пока не будет найдена хорошая замена (если будет).