- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
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 从未被调用,为什么?
更新
最佳答案
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/
据我所知,不能保证 Object.finalize() 总是被调用。但是如果有重要的非GC资源,并且用户没有意外调用close(),我该如何释放该资源?PS。 .NET中的Object.Finaliz
我是一名优秀的程序员,十分优秀!