加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在golang中封装日志设置的正确模式

发布时间:2020-12-16 09:22:06 所属栏目:大数据 来源:网络整理
导读:当尝试将日志设置代码移动到单独的函数时,我遇到无法从主函数隐藏目标文件对象.在下面的INCORRECT简化示例中,尝试通过单个函数调用设置日志写入Stderr和文件: package mainimport ( "io" "log" "os")func SetupLogging() { logFile,err := os.OpenFile("tes
当尝试将日志设置代码移动到单独的函数时,我遇到无法从主函数隐藏目标文件对象.在下面的INCORRECT简化示例中,尝试通过单个函数调用设置日志写入Stderr和文件:

package main

import (
    "io"
    "log"
    "os"
)

func SetupLogging() {
    logFile,err := os.OpenFile("test.log",os.O_APPEND|os.O_CREATE,0666)
    if err != nil {
        log.Panicln(err)
    }
    defer logFile.Close()

    log.SetOutput(io.MultiWriter(os.Stderr,logFile))
}

func main() {
    SetupLogging()
    log.Println("Test message")
}

显然是不起作用,因为defer在SetupLogging函数结束时关闭日志文件.

下面的一个工作示例添加了额外的代码,如果在较大的应用程序中重复作为模式,IMHO会失去一些清晰度:

package main

import (
    "io"
    "log"
    "os"
)

func SetupLogging() *os.File {
    logFile,0666)
    if err != nil {
        log.Panicln(err)
    }

    log.SetOutput(io.MultiWriter(os.Stderr,logFile))
    return logFile
}

func main() {
    logf := SetupLogging()
    defer logf.Close()

    log.Println("Test message")
}

有没有不同的方法将打开文件管理完全封装到一个函数中,但仍然很好地释放句柄?

解决方法

我现在已经成功地在多个项目中使用了以下方法大约一年.我们的想法是从设置调用中返回一个函数.结果函数包含销毁逻辑.这是一个例子:

package main

import (
    "fmt"
    "io"
    "log"
    "os"
)

func LogSetupAndDestruct() func() {
    logFile,os.O_CREATE|os.O_APPEND|os.O_RDWR,logFile))

    return func() {
        e := logFile.Close()
        if e != nil {
            fmt.Fprintf(os.Stderr,"Problem closing the log file: %sn",e)
        }
    }
}

func main() {
    defer LogSetupAndDestruct()()

    log.Println("Test message")
}

它正在使用一个关闭清理逻辑的闭包.

使用这种方法的更详细的公开示例在Viper代码中:here is the return from a test initializer和here it is used to encapsulate the cleanup logic and objects

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读