3 added
3 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В этом уроке мы подробнее разберем работу с пакетами в Go: научимся создавать, экспортировать и импортировать их.</p>
1
<p>В этом уроке мы подробнее разберем работу с пакетами в Go: научимся создавать, экспортировать и импортировать их.</p>
2
<h2>Создание пакета</h2>
2
<h2>Создание пакета</h2>
3
<p>Любой код в Go существует внутри<strong>пакета</strong>- это папка с go-файлами. Заголовки всех файлов в пакете начинаются одинаково -<em>package имя-пакета</em>. Даже если мы создаем программу из одного файла, она все равно должна быть внутри пакета.</p>
3
<p>Любой код в Go существует внутри<strong>пакета</strong>- это папка с go-файлами. Заголовки всех файлов в пакете начинаются одинаково -<em>package имя-пакета</em>. Даже если мы создаем программу из одного файла, она все равно должна быть внутри пакета.</p>
4
<p>Начнем работу с первым Go-пакетом. Создайте папку<em>./greeting/</em>, а внутри нее - файл<em>constants.go</em>. Добавьте в файл такой код:</p>
4
<p>Начнем работу с первым Go-пакетом. Создайте папку<em>./greeting/</em>, а внутри нее - файл<em>constants.go</em>. Добавьте в файл такой код:</p>
5
<p>В сообществе Go-разработчиков принято давать имена пакетам только в нижнем регистре. Не должно быть camelCase, snake_case или kebab-case. Если очень нужно использовать больше одного слова, то стоит использовать аббревиатуру. Хороший пример - пакет<em>bufio</em>(buffer io) из стандартной библиотеки.</p>
5
<p>В сообществе Go-разработчиков принято давать имена пакетам только в нижнем регистре. Не должно быть camelCase, snake_case или kebab-case. Если очень нужно использовать больше одного слова, то стоит использовать аббревиатуру. Хороший пример - пакет<em>bufio</em>(buffer io) из стандартной библиотеки.</p>
6
<p>Проведем небольшой эксперимент - добавим в папку еще один файл<em>getters.go</em>со следующим содержимым:</p>
6
<p>Проведем небольшой эксперимент - добавим в папку еще один файл<em>getters.go</em>со следующим содержимым:</p>
7
<p>Обратите внимание, что переменная greeting объявлена в одном файле, а используется уже в другом. В отличие от других языков, в Go компилятор и линтер не будут ругаться на такой код. Неважно, на сколько файлов разбит пакет, потому что внутри пакета общая область видимости.</p>
7
<p>Обратите внимание, что переменная greeting объявлена в одном файле, а используется уже в другом. В отличие от других языков, в Go компилятор и линтер не будут ругаться на такой код. Неважно, на сколько файлов разбит пакет, потому что внутри пакета общая область видимости.</p>
8
<h2>Пакет main</h2>
8
<h2>Пакет main</h2>
9
<p>Чтобы Go-программу можно было скомпилировать и запустить из командной строки, используют пакет main:</p>
9
<p>Чтобы Go-программу можно было скомпилировать и запустить из командной строки, используют пакет main:</p>
10
<p>Его единственное отличие от любого другого пакета - в нем содержится функция main, которая не принимает аргументы и не возвращает значения. Команды go build и go run ищут функцию main внутри пакета<em>main</em>и собирают исполняемый файл, который вызывает функцию main. Эта функция - точка входа в программу.</p>
10
<p>Его единственное отличие от любого другого пакета - в нем содержится функция main, которая не принимает аргументы и не возвращает значения. Команды go build и go run ищут функцию main внутри пакета<em>main</em>и собирают исполняемый файл, который вызывает функцию main. Эта функция - точка входа в программу.</p>
11
<h2>Импорт и экспорт</h2>
11
<h2>Импорт и экспорт</h2>
12
<p>В Go используется оригинальная система импортов. Воспользуемся созданными выше файлами и изучим импорт на их примере:</p>
12
<p>В Go используется оригинальная система импортов. Воспользуемся созданными выше файлами и изучим импорт на их примере:</p>
13
<p>Структура проекта выглядит так:</p>
13
<p>Структура проекта выглядит так:</p>
14
<p>Чтобы импортировать пакет, достаточно указать относительный или абсолютный путь до него в блоке импортов. При этом в Go нет возможности импортировать только одну переменную или функцию из пакета.</p>
14
<p>Чтобы импортировать пакет, достаточно указать относительный или абсолютный путь до него в блоке импортов. При этом в Go нет возможности импортировать только одну переменную или функцию из пакета.</p>
15
<p>Теперь запустим программу из командной строки:</p>
15
<p>Теперь запустим программу из командной строки:</p>
16
<p>Импортируются ли все переменные из пакета? Обновим функцию main так, чтобы она использовала переменную greeting:</p>
16
<p>Импортируются ли все переменные из пакета? Обновим функцию main так, чтобы она использовала переменную greeting:</p>
17
<p>А теперь запустим:</p>
17
<p>А теперь запустим:</p>
18
<p>Компилятор выдает ошибку: программа не может ссылаться на<strong>не экспортируемое значение</strong>. Рассмотрим подробнее, что это значит.</p>
18
<p>Компилятор выдает ошибку: программа не может ссылаться на<strong>не экспортируемое значение</strong>. Рассмотрим подробнее, что это значит.</p>
19
<p>Go определяет, экспортируется идентификатор или нет, по его имени:</p>
19
<p>Go определяет, экспортируется идентификатор или нет, по его имени:</p>
20
<ul><li>Если идентификатор начинается с заглавной буквы,<strong>значение экспортируется</strong></li>
20
<ul><li>Если идентификатор начинается с заглавной буквы,<strong>значение экспортируется</strong></li>
21
<li>Если идентификатор начинается со строчной буквы или нижнего подчеркивания,<strong>значение не экспортируется</strong>(доступно только в своем пакете)</li>
21
<li>Если идентификатор начинается со строчной буквы или нижнего подчеркивания,<strong>значение не экспортируется</strong>(доступно только в своем пакете)</li>
22
</ul><h3>Алиасы</h3>
22
</ul><h3>Алиасы</h3>
23
<p>Go-разработчик может оказаться в ситуации, когда нужно импортировать два пакета с одинаковыми именами. Например, он решил выпустить вторую версию пакета greeting и создал папку<em>v2</em>внутри папки<em>greeting</em>. Внутри этой папки всего один файл greeting.go:</p>
23
<p>Go-разработчик может оказаться в ситуации, когда нужно импортировать два пакета с одинаковыми именами. Например, он решил выпустить вторую версию пакета greeting и создал папку<em>v2</em>внутри папки<em>greeting</em>. Внутри этой папки всего один файл greeting.go:</p>
24
<p>Обновим пакет<em>main</em>:</p>
24
<p>Обновим пакет<em>main</em>:</p>
25
<p>Чтобы импортировать два разных пакета с одинаковым именем, мы добавляем<strong>алиасы</strong>к импортам пакетов. Теперь можно обращаться к пакету первой версии по имени<em>greetingv1</em>, а ко второй -<em>greetingv2</em>. Если убрать алиасы, то компилятор вернет ошибку greeting redeclared as imported package name.</p>
25
<p>Чтобы импортировать два разных пакета с одинаковым именем, мы добавляем<strong>алиасы</strong>к импортам пакетов. Теперь можно обращаться к пакету первой версии по имени<em>greetingv1</em>, а ко второй -<em>greetingv2</em>. Если убрать алиасы, то компилятор вернет ошибку greeting redeclared as imported package name.</p>
26
<p>В Go есть способ импортировать все экспортируемые переменные из пакета, при этом не используя имя пакета. Если дать пакету алиас ., то из пакета импортируются все переменные и функции, будто бы они были объявлены внутри текущего пакета.</p>
26
<p>В Go есть способ импортировать все экспортируемые переменные из пакета, при этом не используя имя пакета. Если дать пакету алиас ., то из пакета импортируются все переменные и функции, будто бы они были объявлены внутри текущего пакета.</p>
27
<h2>Выводы</h2>
27
<h2>Выводы</h2>
28
<p>Кратко перечислим основные выводы этого урока:</p>
28
<p>Кратко перечислим основные выводы этого урока:</p>
29
-
<ul><li>Код в проекте делится на пакеты, даже если проект состоит всего из одного файла</li>
29
+
<ul><li>Код в проекте делится на пакеты, даже если проект состоит всего из одного файла.</li>
30
-
<li>Пакет<em>main.go</em>содержит в себе функцию main, которая служит точкой входа в программу</li>
30
+
<li>Пакет<em>main.go</em>содержит в себе функцию main, которая служит точкой входа в программу.</li>
31
-
<li>Чтобы экспортировать функцию или переменную из пакета, достаточно дать ей название с заглавной буквы</li>
31
+
<li>Чтобы экспортировать функцию или переменную из пакета, достаточно дать ей название с заглавной буквы.</li>
32
</ul>
32
</ul>