Полезно оставлять низкоуровневые заявления об отладке/трассировке в критических путях, чтобы их можно было включить с помощью конфигурации времени выполнения. Идея заключается в том, что вы никогда не включаете такой журнал в производство (это может привести к нарушению производительности), но вы можете включить его в производственной среде (например, производственная система отключена для отладки или тестовой системы, которая настроена точно так же, как и в производственной системе).
В этом типе ведения журнала есть специальное требование: стоимость нажатия на отключенный оператор журнала на критическом пути должна быть очень низкой: в идеале это один логический тест.
В C/С++ я бы сделал это с помощью макроса LOG, который не оценивает ни один из его аргументов, пока не проверит флажок. Только если это разрешено, мы вызываем некоторую вспомогательную функцию для форматирования и доставки сообщения журнала.
Итак, как это сделать в Go?
Использование io.Discard с log.Logger - это не стартер: он полностью форматирует сообщение журнала каждый раз, прежде чем выбросить его, если он отключен.
Моя первая мысль -
type EnabledLogger struct { Enabled bool; delegate *log.Logger;... }
// Implement the log.Logger interface methods as:
func (e EnabledLogger) Print(...) { if e.Enabled { e.delegate.Output(...) } }
Это близко. Если я скажу:
myEnabledLogger.Printf("foo %v: %v", x, y)
Он не будет форматировать или записывать что-либо, если отключено, но будет оценивать аргументы x и y. Это нормально для базовых типов или указателей, а не для произвольных вызовов функций - например. для создания значений, которые не имеют метода String().
Я вижу два пути:
Типы обертки для отсрочки вызова:
type Stringify { x *Thing }
func (s Stringify) String() { return someStringFn(s.x) }
enabledLogger.Printf("foo %v", Stringify{&aThing})
Оберните все в ручную проверку:
if enabledLog.Enabled {
enabledLog.Printf("foo %v", someStringFn(x))
}
Оба являются многословными и подверженными ошибкам, слишком легко для кого-то забыть шаг и спокойно ввести неприятную регрессию производительности.
Я начинаю любить Go. Скажите, пожалуйста, это может решить эту проблему:)