为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
拉莫斯之舞 2022-09-19 15:03:46
让我们以这段代码为例,它使记录器写入本地文件而不是标准输出: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()
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

你在寻找这样的东西吗?


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()

    }

}

使用方法:


func main() {

    closerFn := logToFile("filename")

    defer closerFn()


    log.Print("logs to file\n")

}


查看完整回答
反对 回复 2022-09-19
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

一种选择是使用延续传递样式,将要在块内执行的代码作为显式参数传递:defer


func 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)


查看完整回答
反对 回复 2022-09-19
  • 2 回答
  • 0 关注
  • 76 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号