← Все этапы
04 · ПАКЕТЫ И НАДЁЖНОСТЬУрок 20 из 3316 минут

Инициализация программы

Разбираемся, когда запускается init и почему ошибки и внешние ресурсы лучше обрабатывать явно.

Код до main

Функция с точным именем init запускается автоматически после инициализации переменных пакета и до вызова main. Пакет может объявить несколько таких функций; пакеты-зависимости инициализируются раньше пакетов, которые от них зависят. У функции init нет параметров и результатов, и её нельзя вызвать напрямую.

Это удобно для небольшой гарантированной настройки пакета. Но init не может вернуть ошибку, поэтому подключение к сети, открытие базы данных или чтение обязательного файла там скрывает отказ и усложняет управление ресурсом. Такие действия лучше помещать в обычную функцию и явно вызвать из main, где можно проверить ошибку и завершить запуск понятным образом.

Пример

package main

import (
	"fmt"
	"strings"
)

var defaultTags []string

func init() {
	defaultTags = []string{"новое", "популярное"}
}

func loadCatalog() []string {
	return append([]string(nil), defaultTags...)
}

func main() {
	tags := loadCatalog()
	fmt.Println(strings.Join(tags, ", "))
}

Здесь init задаёт небольшие значения по умолчанию до входа в main, а loadCatalog явно возвращает их вызывающему коду. У этой простой операции нет ожидаемой ошибки. Если вместо копирования значений функция читает файл или подключается к ресурсу, объяви ей результат ([]string, error), верни реальную ошибку чтения и обработай её в main.

При нескольких подключённых пакетах все их init выполняются до main, даже если программа не вызывает экспортированные функции пакета. Поэтому не стоит использовать init как скрытый сценарий запуска приложения.

Практика

Попробуйте сами

Напиши программу, в которой init задаёт имя резервного склада «Центральный», а явная функция loadWarehouse(name string) (string, error) возвращает ошибку, если имя пустое. В main передай резервное имя, проверь ошибку и напечатай результат. Затем замени имя на пустую строку и проверь ветку ошибки.

Проверка результата

Как понять, что получилось

При имени «Центральный» программа печатает это имя. При пустом имени печатает понятное сообщение об ошибке и не использует пустой результат. Валидация находится в вызываемой функции, а init только задаёт значение по умолчанию.

Инициализация программы | Go | WebSchool · Go