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

Nun*_*oki 4 go deferred

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

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)
Run Code Online (Sandbox Code Playgroud)

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

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

main() {
   logToFile()
   log.Print("I'm going to end up in stdout\n")
}
Run Code Online (Sandbox Code Playgroud)

可以将其移入其自己的功能中,并且仍然按预期工作吗?

我在打开/关闭数据库连接时遇到过同样的情况。似乎唯一的方法是在 .js 中完成这两件事main(),但我认为如果我们可以将其划分为函数,代码看起来会更简洁,更多 SoC。这是 Go 中的禁忌吗?

col*_*tor 7

你在寻找这样的东西吗?

type closerFunc func() error

func 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

使用:

func main() {
    closerFn := logToFile("filename")
    defer closerFn()

    log.Print("logs to file\n")
}
Run Code Online (Sandbox Code Playgroud)