Перейти к содержимому
Теория · Первая программа · урок 4 из 8

Пакеты и импорт

Вернёмся к рецепту. В рецепте пирога не объясняют, как сделать масло или муку: их берут готовыми. А в начале рецепта стоит список того, что понадобится. В программе на Go всё устроено похоже.

Программе часто нужен готовый код: напечатать текст, перевести буквы в верхний регистр. В Go такой код лежит в пакетах, и программа подключает только те, что ей нужны:

GO
package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.ToUpper("hello")) // HELLO
}

Давайте разберём строку внутри main по шагам:

  1. Вызов strings.ToUpper состоит из имени пакета, точки и имени функции.
  2. Он получает "hello" и возвращает тот же текст заглавными буквами.
  3. Этот результат сразу уходит в 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.

GO
fmt.Println(strings.ToLower("GO"), strings.Repeat("ab", 3)) // go ababab

В этой строке три вызова:

  1. strings.ToLower("GO") возвращает go строчными буквами.
  2. strings.Repeat("ab", 3) повторяет ab три раза.
  3. fmt.Println печатает оба результата через пробел.

Частая ошибка

Имя функции из пакета написано со строчной буквы:

GO
package main

import "fmt"

func main() {
    fmt.println("hello") // ✗
}
TEXT
undefined: fmt.println (but have Println)

В пакете fmt нет экспортированного имени println, поэтому компилятор его не находит. В скобках он подсказывает имя, которое есть, — Println.

Главное

  • Пакет — это все файлы .go одной директории, которые компилируются вместе.
  • package main вместе с функцией main даёт исполняемую программу, а пакет с другим именем — библиотека.
  • Импорт подключает пакет по пути в кавычках, а в коде к нему обращаются по имени: strings.ToUpper.
  • Снаружи пакета видны только имена с заглавной буквы.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом