gpt4 book ai didi

go - 为什么永远不会调用终结器?

转载 作者:数据小太阳 更新时间:2023-10-29 03:43:23 31 4
gpt4 key购买 nike

var p = &sync.Pool{
New: func() interface{} {
return &serveconn{}
},
}

func newServeConn() *serveconn {
sc := p.Get().(*serveconn)
runtime.SetFinalizer(sc, (*serveconn).finalize)
fmt.Println(sc, "SetFinalizer")
return sc
}

func (sc *serveconn) finalize() {
fmt.Println(sc, "finalize")
*sc = serveconn{}
runtime.SetFinalizer(sc, nil)
p.Put(sc)
}

上面的代码试图通过 SetFinalizer 重用对象,但调试后我发现 finalizer 从未被调用,为什么?

更新

这可能是相关的:https://github.com/golang/go/issues/2368

最佳答案

The above code tries to reuse object by SetFinalizer, but after debug I found finalizer is never called, why?

终结器仅在 GC 时在对象上调用将其标记为未使用,然后尝试在最后清扫(免费)GC 循环。

作为必然结果,如果在程序运行期间从未执行 GC 循环,则可能永远不会调用您设置的终结器。

以防万一您可能对 Go 的 GC 持有错误的假设,可能值得注意的是 Go 不对值使用引用计数;相反,它使用与程序并行工作的 GC,并且它工作的 session 定期发生,并由某些参数触发,例如分配产生的堆压力。

一些关于终结器的注释:

  • 程序终止时,不会强制运行GC。

    一个推论是终结器不能保证根本无法运行。

  • 如果 GC 在即将释放的对象上找到终结器,它调用终结器但不释放对象。

    对象本身只会在下一个 GC 周期被释放 —浪费内存。

总而言之,您似乎在尝试实现析构函数。请不要:让您的对象实现称为 Close 的标准方法,并在您的类型的契约(Contract)中声明程序员在完成对象后必须调用它。当程序员无论如何都想调用这样的方法时,他们会使用 defer

请注意,此方法适用于 Go 中的所有类型stdlib 包装操作系统提供的资源——文件和套接字描述符。因此,无需假装您的类型有所不同。

要记住的另一件有用的事情是,Go 被明确设计为严肃、简洁、没有魔法、 面对面的语言,您只是在尝试给它添加魔力。请不要,那些喜欢解密魔法层的人会使用 Scala 不同的语言进行编程。

关于go - 为什么永远不会调用终结器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52927975/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com