Пакеты и импорт
Вернёмся к рецепту. В рецепте пирога не объясняют, как сделать масло или муку: их берут готовыми. А в начале рецепта стоит список того, что понадобится. В программе на Go всё устроено похоже.
Программе часто нужен готовый код: напечатать текст, перевести буквы в верхний регистр. В Go такой код лежит в пакетах, и программа подключает только те, что ей нужны:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToUpper("hello")) // HELLO
}Давайте разберём строку внутри main по шагам:
- Вызов
strings.ToUpperсостоит из имени пакета, точки и имени функции. - Он получает
"hello"и возвращает тот же текст заглавными буквами. - Этот результат сразу уходит в
fmt.Println, и программа печатаетHELLO.
Блок import
Блок import в начале файла — это список продуктов из рецепта. Каждый импорт подключает один пакет. Записать импорты можно в одной из двух форм.
Здесь аналогия со списком продуктов неточна в одном. Лишний продукт в списке ничему не мешает, а лишний импорт останавливает сборку — вы видели это в уроке об ошибках компиляции.
Один пакет
Запись import "fmt" состоит из двух частей:
import— ключевое слово «подключаю пакет»;"fmt"— путь к пакету в двойных кавычках.
Эту форму пишут, когда программе нужен один пакет: например, ей нужно только печатать текст через fmt.
Группа пакетов
Несколько импортов объединяют в группу. После слова import открывают круглую скобку, пишут пути по одному на строку и закрывают скобку — как в примере выше.
Можно написать и два отдельных импорта подряд, import "fmt" и import "strings", — программа тоже соберётся. Но обычно пишут именно группу: она короче и читается как один список.
Путь и имя пакета
Импорт указывает путь к пакету, а код обращается к пакету по имени:
- путь пишут в кавычках:
"fmt","strings","math/rand"; - имя пакета в коде обычно совпадает с последней частью пути: у
"math/rand"этоrand; - пакеты стандартной библиотеки устанавливаются вместе с Go, поэтому их импортируют без скачивания.
Пакет — это директория
Пакет — это все файлы .go из одной директории (папки), которые компилируются вместе. Из этого следуют три правила:
- каждый файл пакета начинается со строки
packageс одним и тем же именем; - функция, объявленная в одном файле пакета, видна в остальных его файлах без импорта;
- имя пакета обычно совпадает с именем директории, а программа с
package mainможет лежать в директории с любым именем.
Программа и библиотека
По имени в строке package пакеты делятся на два вида.
Пакет main
Пакет с именем main особый: вместе с функцией main он даёт исполняемую программу, и её выполнение начинается с main. Именно его собирают команды go run и go build.
Функция main обязательна. Без неё сборка остановится с ошибкой function main is undeclared in the main package.
Библиотека
Пакет с любым другим именем — библиотека. Сам по себе он не запускается: его функции вызывают другие пакеты, которые его импортируют.
fmt и strings — как раз такие библиотеки. Команда go run для файла библиотеки отвечает ошибкой: запускать в нём нечего.
Ответ на собеседовании
Этот вопрос часто задают на собеседовании: «Что такое пакет и что делают package main и import?» Ответ складывается из трёх фактов этого урока:
- пакет — это файлы одной директории;
package mainс функциейmain— точка входа программы;importподключает другой пакет по пути, а неиспользованный импорт — ошибка компиляции.
Экспортированные имена
Снаружи пакета видны только имена, которые начинаются с заглавной буквы, — экспортированные имена. Поэтому Println и ToUpper пишутся с большой буквы.
Имя со строчной буквы остаётся внутри своего пакета, и импорт его не открывает. Правило касается всех имён, не только функций: значение math.Pi видно снаружи, потому что начинается с заглавной P.
fmt.Println(strings.ToLower("GO"), strings.Repeat("ab", 3)) // go abababВ этой строке три вызова:
strings.ToLower("GO")возвращаетgoстрочными буквами.strings.Repeat("ab", 3)повторяетabтри раза.fmt.Printlnпечатает оба результата через пробел.
Частая ошибка
Имя функции из пакета написано со строчной буквы:
package main
import "fmt"
func main() {
fmt.println("hello") // ✗
}undefined: fmt.println (but have Println)В пакете fmt нет экспортированного имени println, поэтому компилятор его не находит. В скобках он подсказывает имя, которое есть, — Println.
Главное
- Пакет — это все файлы
.goодной директории, которые компилируются вместе. package mainвместе с функциейmainдаёт исполняемую программу, а пакет с другим именем — библиотека.- Импорт подключает пакет по пути в кавычках, а в коде к нему обращаются по имени:
strings.ToUpper. - Снаружи пакета видны только имена с заглавной буквы.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.