【问题标题】:Should I be using fmt in production code?我应该在生产代码中使用 fmt 吗?
【发布时间】:2016-04-18 17:27:54
【问题描述】:

我看到很多类似这样的Go 代码:

func main() {
    response, _, err := http.Get("http://golang.org/")
    if err != nil {
        fmt.Printf("%s", err)
        os.Exit(1)
    }

    defer response.Body.Close()
    contents, err := ioutil.ReadAll(response.Body)
    if err != nil {
        fmt.Printf("%s", err)
        os.Exit(1)
    }

    fmt.Printf("%s\n", string(contents))
}

我的问题是:

  1. 在生产中,我应该保留这些fmt.Printf 语句吗?愚蠢的问题我确定,但只是检查

  2. 对于生产代码和开发代码,您推荐哪些日志记录选项?

【问题讨论】:

  • 不知道为什么代码格式化不起作用,我尝试修复了几次。
  • 在不了解您的应用程序的情况下很难回答这个问题。上面的代码在某些情况下是可以接受的,在其他情况下是不可接受的。
  • 请注意,使用log.Fatal*() 函数集可以很好地完成“打印和退出”序列。
  • 我认为在生产代码中使用 fmt 包没有任何问题。除非fmt.Sprintf 有问题,否则我不知道。

标签: logging go production-environment


【解决方案1】:

fmt.Printf() 非常适合开始草拟您的程序,但您可能应该删除它们或替换为真正的日志记录语句。

如果我需要更多标准 loglogrus,我已经很幸运了。

所有日志记录都取决于其他与操作相关的问题,因此谁/什么在处理/查看日志很重要。

【讨论】:

    【解决方案2】:

    认为在某些情况下使用printfs 是可以接受的。最好在生产环境中使用不同的日志记录策略。

    例如,如果您的应用程序是在后台运行的守护程序,那么您将错过所有 fmt.Printf,除非您不将它们通过管道传输到文件中。

    进行 looging 的一个好方法是使用日志轮换(因为您不想拥有非常大的文件)而不是重新发明自己的 logrotate,您可以根据需要使用标准包或外部包。

    Golang 提供了一个 logsyslog 子包,它是依赖 OS syslog 进行简单日志记录的最佳解决方案。

    【讨论】:

      【解决方案3】:

      我对此的看法是,对于相对简单的“类似服务”的解决方案(服务用户请求的长期运行程序),如果您切换到 log.Fatal*() 为每个消息输出添加时间戳或在一些明智的主管(systemddaemonrunit 等)下运行您的服务,这会将您的程序输出的内容转发到适当的系统日志接收器。

      日志记录方法也很大程度上取决于程序的性质。 比如说,对于执行一次性操作的命令行应用程序(curlwget 是这种程序的一个很好的例子——按照你的代码示例的精神)记录到他们的标准错误流并退出是唯一理智的操作模式。守护进程(服务)预计将在无人值守的情况下运行,因此您必须确保它们的日志被发送并存储在某个地方,并带有时间戳。

      小提示:行为良好的程序应该将错误消息输出到其标准错误流,因此如果您出于某种原因不想使用log.Fatal*(),至少要使用fmt.Fprint*(os.Stderr, ...)。

      【讨论】:

        【解决方案4】:

        我认为最好的方法是准备代码以便从开发环境轻松切换到生产环境,也许在启动 Go 应用程序时使用输入参数。

        您可以创建不同级别的日志:

        “始终”日志级别

        此日志级别始终启用,提供有关应用程序状态的重要信息(如果需要)。同时报告崩溃消息。

        “测试”日志级别

        当您的代码完成时,此日志级别包含有用的信息,但您必须检查一些在代码投入生产时不再有用的信息

        “调试”日志级别

        当您在开发环境中开发新功能或优化现有代码时,此日志级别包含有用的信息

        在我看来,最好的方法是使用 chans,它允许您创建一个异步守护程序并在任何您想要的任何地方记录。

        您可以阅读有关 chan here 的一些信息。

        守护进程的一个例子可以是:

        func daemonLogging(importantMessage chan error, testingMessage chan error,debugMessage chan error){
            for{
        
                if globalDebugFlag == true{
                    // Log debug message
                }
        
                if globalTestingMessage == true{
                    // Log Testing message
                }
        
                // Log important message
            }
        }
        

        记得用go关键字调用这个函数

        我认为您使用的什么包并不重要(如果您没有任何需要),但重要的是如何您决定记录您的消息

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-21
          • 1970-01-01
          • 1970-01-01
          • 2010-09-22
          • 2019-01-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多