Логирование необходимо любому приложению. Встроенный модуль логирования имеется практически во всех современных языках. И Golang не исключение: модуль log используется прямо «из коробки».
fmt и log
В модуле log имеется три типа диагностических сообщений:
- Print — запись диагностических сообщений.
- Panic — запись диагностических сообщений и выполнение функции
panic(). - Fatal — запись диагностических сообщений и завершение работы с кодом.
Хотя назначение этих сообщений и функций Print, Panic, Fatal в fmt одинаковое, различия имеются:
package main
import (
"fmt"
"log"
)
func main() {
fmt.Print("First print statement")
fmt.Printf("Second print statement")
fmt.Println("Third print statement")
log.Print("First Log message")
log.Printf("Second Log message")
log.Println("Third Log message")
l := log.Default()
l.Print("First Log message")
l.Printf("Second Log message")
l.Println("Third Log message")
}
// Вывод
// Первый оператор печатиВторой оператор печатиТретий оператор печати
// 2022/12/26 20:21:36 Первое диагностическое сообщение
// 2022/12/26 20:21:36 Второе диагностическое сообщение
// 2022/12/26 20:21:36 Третье диагностическое сообщение
// 2022/12/26 20:21:36 Первое диагностическое сообщение
// 2022/12/26 20:21:36 Второе диагностическое сообщение
// 2022/12/26 20:21:36 Третье диагностическое сообщение
Итак, у модуля log то же назначение, что и у функций print/panic/fatal модуля fmt. Первое отличие: модулем log в конце всегда добавляется символ новой строки, если его нет. Именно поэтому все три оператора печати fmt оказались в одной строке, а все диагностические сообщения — в разных.
Поэтому в модуле log функции Print и Println эквивалентны. Их реализации тоже абсолютно одинаковы.
Другое очевидное отличие: в начало модулем log добавляется информация о логе. По умолчанию это дата и время.
Настройка формата логов
package main
import (
"log"
"os"
)
func main() {
InfoLog := log.New(os.Stdout, "Info: ", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile)
InfoLog.Print("First Log message")
DebugLog := log.New(os.Stdout, "Debug: ", log.Ldate|log.Ltime|log.Llongfile)
DebugLog.Print("First Log message")
ErrorLog := log.Default()
ErrorLog.SetPrefix("Error: ")
ErrorLog.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
f, err := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
panic(err)
}
defer f.Close()
ErrorLog.SetOutput(f)
ErrorLog.Print("First Log message")
}
Вывод в файл error.log:
Ошибка: 2022/12/26 21:50:22.715153 main.go:23: Первое диагностическое сообщение
Вывод в STDOUT, стандартный вывод терминала:
Информация: 2022/12/26 21:50:22.715100 main.go:10: Первое диагностическое сообщение
Отладка: 2022/12/26 21:50:22 /home/golang/logger/main.go:13: Первое диагностическое сообщение
В первом объекте log при помощи New создан новый объект журнала и присвоен переменной InfoLog. Функции New требуется три аргумента:
os.Stdout— этим определяется, что лог запишется в терминал.“Info:”— это строковое значение, которое добавляется в начало лог-инструкции.log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile— этим определяется все, что между“Info:”и сообщением. Здесь генерируется значение2022/12/25 21:50:22.715100 main.go:10.
Аналогично DebugLog инициализируется при помощью New с похожими аргументами.
Все аргументы, передаваемые в New, задаются отдельно при помощи функций SetOutput, SetPrefix и SetFlags. Этими же функциями задаются пользовательские значения в ErrorLog, в котором “error.log” задается лог-файлом.
f, err := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
panic(err)
}
ErrorLog.SetOutput(f)
Функции SetOutput требуется объект типа io.Writer. То есть используется объект любого type, которым реализованы функции Write. Из os.OpenFile возвращается объект *os.File, соответствующий интерфейсу io.Writer.
Заключение
Настройка логов — фундаментальная, неотъемлемая часть программирования. В примерах мы показали, что встроенными модулями log эта задача решается быстро.
Читайте также:
- Космическое приключение компилятора Golang
- Контейнеризация проекта GO с Envoy
- Как использовать горутины правильно
Читайте нас в Telegram, VK и Дзен
Перевод статьи Naitik Gala: Writing logs in Golang





