Главные вопросы — перезапись существующего файла, обработка ошибок и управление закрытием. Value receiver сам по себе не ломает код: копируется указатель на один и тот же os.File.
Возможные проблемы в реализации логгера
Главные вопросы — перезапись существующего файла, обработка ошибок и управление закрытием. Value receiver сам по себе не ломает код: копируется указатель на один и тот же os.File.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Рассмотрим типичный пример создания простого логгера, записывающего сообщения в файл. Важно обратить внимание на потенциальные ошибки в реализации, такие как неверное управление ресурсами, отсутствие указателей в методах‑получателях и прочее.
type LogWriter interface {
Log(message string) error
Close() error
}
type DiskLogger struct{ outFile *os.File }
func NewDiskLogger(fileName string) (*DiskLogger, error) {
f, err := os.Create(fileName)
if err != nil {
return nil, err
}
return &DiskLogger{f}, nil
}
func (dl DiskLogger) Log(message string) error {
_, err := dl.outFile.WriteString(message + "\n")
return err
}
func (dl DiskLogger) Close() error {
return dl.outFile.Close()
}
В этом фрагменте кода можно обсудить, какие ошибки могут возникнуть при его использовании и как их исправить.
Ответ
Главные вопросы — перезапись существующего файла, обработка ошибок и управление закрытием. Value receiver сам по себе не ломает код: копируется указатель на один и тот же os.File.
os.Create обрезает существующий файл; для накопления логов нужен согласованный режим append. Ошибки Log и Close должен проверять вызывающий, а жизненный цикл не должен допускать записи после Close. Методы os.File допускают конкурентное использование, но это не заменяет требования к порядку записей и координации завершения. При добавлении mutex используйте pointer receiver и не копируйте логгер. Успешный Write не равен гарантированной долговременной записи без дополнительных требований к Sync.