Golang中的跨平台日志记录

huangapple go评论73阅读模式
英文:

cross platform logging in Golang

问题

我正在开发一个在 Mac 上的 Go 程序,该程序安装了 Parallels 并在 Windows 上进行测试。我的程序工作得很好。我可以在 Mac 上编译一个 Windows 的 ".exe" 文件,并在 Windows 上运行它,除了日志文件之外,其他都正常。

我已经设置了日志记录器将其输出写入文件,如下所示:

log.SetOutput(projectsLog)

其中 projectsLog 在上面声明如下:

projectsLog *os.File

我使用 log.Printf 语句,因为我想要格式化的输出。下面是一个示例:

log.Printf("Error: wrong Hra Class value %s in row %v for project/path %s", hraClass, (rowNum + 1), testDir)

这在 Mac 上运行得很好。每行使用 log.Printf 的日志都会单独记录在一行上,但在 Windows 上,换行符不显示,我得到的是一行没有换行符的日志。我很清楚 Unix 和 Windows 之间的 "\r" 和 "\r\n" 的区别。但我认为 log.Printf 会根据运行的平台自动适应,我的假设是错误的吗?

如果我的假设是错误的,那么我有哪些选项可以确保日志文件在 Windows 上可读?如果可能的话,我不想传递标志,比如 -platform windows 或类似的东西。这个问题能以透明的方式处理吗?

英文:

I am developing a Go program on a Mac which has Parallels installed with Windows so that I can test on both platforms. My program works well. I can compile a Windows ".exe" file on my Mac and run it from Windows and it works well except the log file.

I have set the logger to write its output to a file like so:

log.SetOutput(projectsLog)

Where projectsLog is declare above it as shown below:

projectsLog *os.File

I am using log.Printf statements since I want formatted output. An example is shown below:

log.Printf("Error: wrong Hra Class value %s in row %v for project/path %s", hraClass, (rowNum + 1), testDir)

This is working great on Mac. Each line using log.Printf is logged on a separate line, but on Windows the line breaks do not show and I get one lines without line breaks. I am well aware of "\r" and "\r\n" difference between unix and windows. But I thought that log.Printf will behave appropriately based on the platform it is run on?

If my assumption is wrong then what are some of the options that I have to make sure that the log file is readable on Windows? If I can, I do not want to pass flags, e.g., -platform windows or some such thing. Can this be handled in a transparent manner?

答案1

得分: 1

如前所述,fmt 包始终使用 \n 作为换行符 "序列",无论操作系统如何(包括 Windows)。log 包在底层使用 fmt,因此对于 log 也是一样的。当调用不以 ...ln() 结尾的函数时(例如 log.Printf()),会明确打印一个 \n,如 Logger.Output() 中所记录的(log.Printf() 转发到该函数)。

\n 视为换行符处理即可。如果确实需要打印 \r\n,则必须通过在格式字符串末尾附加 \r 字符来手动处理,例如:

log.Printf("这将以 CR+LF 结尾\r") // \n 会自动附加

你可以为此创建一个包装函数:

func winprintf(format string, a ...interface{}) {
    log.Printf(format+"\r", a...)
}

请注意,这只会在日志条目的末尾打印 \r\n;但是,如果在格式字符串中使用 \n,或者参数是包含 \n 的字符串(或通过调用它们的 String() 方法将结果转换为字符串),这些都不会自动转换为 \r\n。你可以使用 strings.Replace() 来处理这些情况。

英文:

As noted, the fmt package always uses \n as the newline "sequence" regardless of the OS (on Windows too). The log package uses fmt under the hood, so the same applies to log too. When functions that do not end with ...ln() are called (e.g. log.Printf()), a \n will be printed explicitly as documented at Logger.Output() (to which log.Printf() forwards to).

Just deal with \n as the newline. If you do need to print \r\n, you have to handle that manually by appending a \r character at the end of the format string, e.g.:

log.Printf("This will be terminated by CR+LF\r") // \n is appended automatically

You may create a wrapper function for it:

func winprintf(format string, a ...interface{}) {
	log.Printf(format+"\r", a...)
}

Note that this however will only print \r\n at the end of the log entry; but if you use \n inside the format string or the arguments are strings (or will result in a string by calling their String() method) containing \n, those will not turn into \r\n automatically. You may use strings.Replace() to handle those too.

huangapple
  • 本文由 发表于 2016年2月22日 22:05:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/35555692.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定