当资源超出周围函数的范围时,如何推迟资源清理?

让我们以这段代码为例,它使记录器写入本地文件而不是标准输出:


f, err := os.OpenFile("filename", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)

if err != nil {

        log.Fatal(err)

}   


defer f.Close()


log.SetOutput(f)

作者将此代码直接放入函数中,使其按预期工作。但是,如果我想把这个代码放到一个专用的函数中,然后调用它,那么它将不再起作用,因为在使用记录器之前会调用它。main()main()f.Close()


例如(如果上面的代码现在位于名为 的函数中):logToFile()


main() {

   logToFile()

   log.Print("I'm going to end up in stdout\n")

}

这是否可以移动到自己的功能中,并且仍然按预期工作?


我在打开/关闭数据库连接时也遇到过同样的情况。而且似乎唯一的方法就是在 里面做这两件事,但我认为如果我们能把它分成函数,代码看起来会更干净,更SoC。这是围棋中的禁忌吗?main()


拉莫斯之舞
浏览 115回答 2
2回答

侃侃无极

你在寻找这样的东西吗?type closerFunc func() errorfunc logToFile(path string) closerFunc {    f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)    if err != nil {        log.Fatal(err)    }       log.SetOutput(f)    return func() error {        return f.Close()    }}使用方法:func main() {    closerFn := logToFile("filename")    defer closerFn()    log.Print("logs to file\n")}

慕尼黑5688855

一种选择是使用延续传递样式,将要在块内执行的代码作为显式参数传递:deferfunc withLogToFile(filename string, body func()) {    f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)    if err != nil {        log.Fatal(err)    }    prevOut := log.Writer()    log.SetOutput(f)    defer func() {        log.SetOutput(prevOut)        if err := f.Close(); err != nil {            log.Fatal(err)        }    }()    body()}然后呼叫站点变为:func main() {    withLogToFile(filename, func() {        log.Print("I'm going to end up in ", filename)    })}(https://play.golang.org/p/ebCvtzufU5U)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go