HTML Diff
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>