Пакеты и повторное использование кода

Эта глава переносит нас из плоскости написания «скриптов» в плоскость создания настоящих систем. В современном Go (версии 1.11+ и тем более в 2026 году) управление кодом строится вокруг модулей. Мы больше не привязаны к жесткой структуре папок GOPATH.

Go поощряет хорошие инженерные практики, одна из которых — принцип DRY (Don’t Repeat Yourself — «не повторяйся»). Мы уже знаем, что функции позволяют не дублировать код внутри одного файла. Но как использовать один и тот же код в разных проектах? Для этого в Go существуют пакеты.

Вы уже знакомы с пакетом fmt. Это стандартный пакет для форматирования и вывода данных. Разделение кода на пакеты дает три важных преимущества:

  1. Управление именами: Функции внутри пакета math могут называться просто Average, не боясь конфликта с функцией Average из другого пакета.
  2. Организация: Код логически разбит на части, что упрощает навигацию.
  3. Скорость компиляции: Go компилирует каждый пакет отдельно. Если вы изменили один файл в main, пакет fmt пересобирать не нужно.

Создание модуля и пакета

В современном Go работа начинается с создания модуля. Модуль — это коллекция пакетов.

Шаг 1: Инициализация модуля

Создайте новую папку my-project и выполните в ней команду:

go mod init my-project

Это создаст файл go.mod, который сделает вашу папку корнем проекта.

Шаг 2: Создание структуры папок

Для чистоты кода создадим подпапку math для нашего кастомного пакета:

  1. Создайте папку math.
  2. В ней создайте файл math.go.
// math/math.go
package math // Название пакета должно совпадать с папкой

// Average находит среднее значение в срезе чисел.
// Название начинается с заглавной буквы, чтобы функция была "экспортируемой".
func Average(xs []float64) float64 {
    total := 0.0
    for _, x := range xs {
        total += x
    }
    return total / float64(len(xs))
}

Шаг 3: Использование пакета в main

Теперь в корневой папке создайте main.go:

// main.go
package main

import (
    "fmt"
    "my-project/math" // Импортируем наш пакет по пути: <имя_модуля>/<папка>
)

func main() {
    xs := []float64{1, 2, 3, 4}
    avg := math.Average(xs)
    fmt.Println("Среднее:", avg)
}


Видимость: Экспортируемые и скрытые имена

Это важнейшая концепция Go. Видимость функции или переменной за пределами пакета определяется регистром первой буквы.

  • Average (с большой буквы) — экспортируемая (Public). Доступна любым другим пакетам.
  • average (с маленькой буквы) — неэкспортируемая (Private). Доступна только внутри текущего пакета.

[!TIP] Совет эксперта Всегда делайте видимыми только те части кода, которые действительно нужны пользователю вашего пакета. Это называется инкапсуляцией и позволяет вам менять внутреннюю логику пакета, не ломая чужие программы.


Псевдонимы пакетов

Если названия пакетов из разных библиотек совпадают, вы можете назначить им псевдоним (алиас):

import m "my-project/math"

func main() {
    avg := m.Average(xs) // Теперь обращаемся через 'm'
}


Документация в Go

Go делает документирование кода невероятно простым. Достаточно написать комментарий непосредственно перед объявлением функции.

Чтобы посмотреть документацию в терминале, используйте встроенную команду go doc:

go doc math.Average

Если вы хотите увидеть красивую веб-страницу со всей документацией вашего проекта (аналог официального сайта pkg.go.dev), используйте инструмент pkgsite (пришел на смену старому godoc):

  1. Установите его: go install golang.org/x/pkgsite/cmd/pkgsite@latest
  2. Запустите в папке проекта: pkgsite -p 6060
  3. Откройте http://localhost:6060 в браузере.

Задачи

  • Теория: Почему в Go нет ключевых слов public или private? Как их заменяет язык?
  • Псевдоним: Создайте алиас для пакета fmt и выведите текст с его помощью.
  • Расширение: Добавьте в ваш пакет math две новые функции:
  • Min([]float64) float64 — поиск минимального числа.
  • Max([]float64) float64 — поиск максимального числа.

  • Документирование: Напишите комментарии к новым функциям и проверьте, как они отображаются через go doc.
  • Модули: Посмотрите содержимое файла go.mod. Что там изменилось после написания кода?

Полезные ссылки

  1. Go Modules Reference — всё о модулях.
  2. Effective Go: Package Names — как правильно называть пакеты.
  3. Go Blog: Package Management — история и практика управления зависимостями.