Полное описание пакета log в Go

Полное описание пакета log в Go с примерами применения и разными потоками вывода

Пакет log в Go предоставляет простые и эффективные инструменты для логирования. Он поддерживает:

  • Вывод логов в стандартный вывод (stdout/stderr).
  • Настройку формата вывода (префиксы, дата/время, уровень логирования).
  • Запись логов в файлы.
  • Гибкую настройку через log.Logger.

1. Основные функции пакета log

1.1. Простое логирование

Пакет log предоставляет стандартные функции:

log.Print("Обычное сообщение")       // Вывод без формата
log.Printf("Формат: %d", 123)       // Форматированный вывод
log.Println("Сообщение с новой строкой") // Вывод с \n

1.2. Логирование с уровнем FATAL (завершение программы)

log.Fatal("Сообщение и выход с os.Exit(1)")    // Вывод + exit(1)
log.Fatalf("Формат: %s", "ошибка")            // Форматированный вывод + exit(1)
log.Fatalln("Фатальная ошибка")                // Вывод + exit(1)

1.3. Логирование с уровнем PANIC (вызов паники)

log.Panic("Паника с выводом стека")    // Вывод + panic()
log.Panicf("Ошибка: %v", err)         // Форматированный вывод + panic()
log.Panicln("Критическая ошибка")     // Вывод + panic()

2. Настройка формата вывода

2.1. Добавление префикса (дата, время, уровень)

log.SetPrefix("ERROR: ") // Установка префикса
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) // Формат
log.Println("Сообщение с префиксом")

Вывод:

ERROR: 2024/03/15 14:20:10 main.go:10: Сообщение с префиксом

2.2. Доступные флаги для log.SetFlags

Флаг Описание
log.Ldate Дата (2006/01/02)
log.Ltime Время (15:04:05)
log.Lmicroseconds Микросекунды (15:04:05.000000)
log.Llongfile Полный путь к файлу (/a/b/c.go:10)
log.Lshortfile Короткое имя файла (c.go:10)
log.LUTC Вывод времени в UTC
log.Lmsgprefix Префикс перед сообщением (Go 1.14+)

Пример комбинации флагов:

log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile | log.Lmsgprefix)

3. Запись логов в файл

file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
    log.Fatal("Ошибка открытия файла:", err)
}
defer file.Close()

log.SetOutput(file) // Перенаправляем вывод в файл
log.Println("Сообщение записано в app.log")

4. Создание нескольких логгеров

Можно создавать отдельные логгеры для разных целей:

logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime)
errorLogger := log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)

logger.Println("Информационное сообщение")
errorLogger.Println("Ошибка в программе")

Вывод:

INFO: 2024/03/15 14:20:10 Информационное сообщение
ERROR: 2024/03/15 14:20:10 main.go:15: Ошибка в программе

5. Продвинутое использование (JSON-логирование, уровни)

Стандартный log не поддерживает уровни (DEBUG, INFO, WARN, ERROR), но их можно эмулировать:

5.1. Логирование в JSON

type LogEntry struct {
    Level   string `json:"level"`
    Message string `json:"message"`
    Time    string `json:"time"`
}

func JSONLog(level, message string) {
    entry := LogEntry{
        Level:   level,
        Message: message,
        Time:    time.Now().Format(time.RFC3339),
    }
    data, _ := json.Marshal(entry)
    log.Println(string(data))
}

JSONLog("INFO", "Запуск сервера")

Вывод:

{"level":"INFO","message":"Запуск сервера","time":"2024-03-15T14:20:10Z"}

5.2. Уровни логирования

const (
    LevelDebug = "DEBUG"
    LevelInfo  = "INFO"
    LevelWarn  = "WARN"
    LevelError = "ERROR"
)

func Log(level, message string) {
    log.Printf("[%s] %s", level, message)
}

Log(LevelError, "Сервер не отвечает")

Вывод:

$$[ERROR] Сервер не отвечает$$

6. Когда использовать log, а когда другие пакеты?

  • log — для простых задач (CLI-утилиты, маленькие сервисы).
  • slog (Go 1.21+) — структурированное логирование с уровнями.
  • zap/zerolog — для высоконагруженных приложений (минимальные аллокации).

Вывод

  • Пакет log прост, но гибок (префиксы, файлы, форматирование).
  • Подходит для базового логирования.
  • Для сложных сценариев лучше использовать slog, zap или zerolog.
  • Можно комбинировать с io.MultiWriter для вывода в несколько мест.

Пример MultiWriter:

file, _ := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
multiWriter := io.MultiWriter(os.Stdout, file)
log.SetOutput(multiWriter)
log.Println("Сообщение в консоль и файл")