亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 golang 中封裝日志設置的正確模式

在 golang 中封裝日志設置的正確模式

Go
一只甜甜圈 2021-08-10 15:35:37
當嘗試將日志設置代碼移動到單獨的函數中時,我無法從main函數中隱藏目標文件對象。在以下INCORRECT簡化示例中,嘗試通過單個函數調用將日志寫入 Stderr 和文件:package mainimport (    "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函數結束時關閉了日志文件。下面的一個工作示例添加了額外的代碼,恕我直言,如果在更大的應用程序中作為模式重復,則會失去一些清晰度:package mainimport (    "io"    "log"    "os")func SetupLogging() *os.File {    logFile, err := os.OpenFile("test.log", os.O_APPEND|os.O_CREATE, 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")}有沒有一種不同的方法可以將打開的文件管理完全封裝到一個函數中,但仍然可以很好地釋放句柄?
查看完整描述

3 回答

?
波斯汪

TA貢獻1811條經驗 獲得超4個贊

這樣做的正確方法是將 main 中的句柄傳遞給SetupLogging:


func SetupLogging(lf *os.File) {

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

    log.Println("Started")

}


func main() {

    logFile, err := os.OpenFile("test.log", os.O_APPEND|os.O_CREATE, 0666)

    if err != nil {

        log.Panicln(err)

    }

    defer logFile.Close()

    SetupLogging(logFile)

    log.Println("Test message")

}

另一種選擇是使用runtime.SetFinalizer,但并不總是保證在主退出之前運行。


func SetupLogging() {

    logFile, err := os.OpenFile("test.log", os.O_APPEND|os.O_CREATE, 0666)

    if err != nil {

        log.Panicln(err)

    }

    runtime.SetFinalizer(logFile, func(h *os.File) {

        h.Close()

    })


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

}


查看完整回答
反對 回復 2021-08-10
?
皈依舞

TA貢獻1851條經驗 獲得超3個贊

我現在已經在多個項目中成功使用了以下方法大約一年。這個想法是從設置調用返回一個函數。結果函數包含銷毀邏輯。下面是一個例子:


package main


import (

    "fmt"

    "io"

    "log"

    "os"

)


func LogSetupAndDestruct() func() {

    logFile, err := os.OpenFile("test.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)

    if err != nil {

        log.Panicln(err)

    }


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


    return func() {

        e := logFile.Close()

        if e != nil {

            fmt.Fprintf(os.Stderr, "Problem closing the log file: %s\n", e)

        }

    }

}


func main() {

    defer LogSetupAndDestruct()()


    log.Println("Test message")

}

它在被延遲的清理邏輯周圍使用了一個閉包。


查看完整回答
反對 回復 2021-08-10
  • 3 回答
  • 0 關注
  • 261 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號