Как зарегистрировать fmt.Printf в пользовательском файле

#go

#Вперед

Вопрос:

У меня есть эта функция, которую я использую для регистрации:

 func formattedLog(prefix, m string, color int) {
    fmt.Printf("33[%dm%s", color, DateTimeFormat)
    fmt.Printf("▶ %s: %s33[%dmn", prefix, m, int(Black))
}
  

Я хочу сохранить выходные данные моего журнала в каком-либо файле:

 f, err := os.OpenFile("../../../go-logs.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
    log.Fatal("error opening logs file", err)
}
defer f.Close()
//set output of logs to f
log.SetOutput(f)
log.Println("This is a test log entry") // <====This logs in file
  

но когда я вызываю свою функцию, которая использует fmt.Printf он не регистрируется в файле go-logs.txt :

 formattedErr("ERR", msg, err.Error(), int(Red))
  

есть ли в любом случае setoutput также для fmt.Printf

Комментарии:

1. Зачем вам нужно использовать fmt.Printf ? Вы можете использовать fmt.Fprintf для записи в файл, log.Printf для записи через глобальный регистратор, log.SetPrefix чтобы поместить префикс в глобальный регистратор и log.New создать неглобальный регистратор (последнее я лично рекомендовал бы для любого нетривиального проекта). Хотя вы можете перезаписать глобальные переменные в других пакетах, я лично считаю, что это должно быть решением последней инстанции.

Ответ №1:

fmt.Printf() документы, которые он записывает в стандартный вывод:

Printf форматирует в соответствии со спецификатором формата и записывает в стандартный вывод.

Таким образом, нет fmt.SetOutput() возможности перенаправить это в ваш файл.

Но обратите внимание, что стандартный вывод — это переменная в os пакете:

Stdin, Stdout и Stderr — это открытые файлы, указывающие на стандартный ввод, стандартный вывод и стандартные файловые дескрипторы ошибок.

Обратите внимание, что среда выполнения Go записывает в стандартную ошибку при панике и сбоях; закрытие Stderr может привести к тому, что эти сообщения отправятся в другое место, возможно, в файл, открытый позже.

 var (
        Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
        Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
        Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
  

И вам разрешено установить свое собственное os.File значение os.Stdout . Хотя это не очень хорошая идея использовать то же самое os.File для регистратора, а также устанавливать для него значение os.Stdout , доступ к его File.Write() методу не будет синхронизирован между fmt пакетом и регистратором.

Лучше всего было бы использовать log.Logger везде (выходные данные которого вы правильно настроили, чтобы сообщения журнала были должным образом сериализованы).