猿问

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

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)

}

上面的代码尝试重用 object by SetFinalizer,但调试后我发现 finalizer 从未被调用,为什么?


更新


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


泛舟湖上清波郎朗
浏览 120回答 1
1回答

繁星coding

上面的代码尝试重用 object by SetFinalizer,但调试后我发现 finalizer 从未被调用,为什么?仅当 GC 将对象标记为未使用时才会调用终结器,然后在 GC 周期结束时尝试清扫(释放)。作为必然结果,如果在程序运行期间从未执行 GC 循环,则可能永远不会调用您设置的终结器。以防万一您可能对 Go 的 GC 持有错误的假设,可能值得注意的是 Go 不对值使用引用计数;相反,它使用与程序并行工作的 GC,并且它工作的会话定期发生,并由某些参数触发,例如分配产生的堆压力。关于终结器的一些注释:当程序终止时,不会强制运行 GC。这样做的一个必然结果是终结器根本不能保证运行。如果 GC 在将要释放的对象上找到终结器,它会调用终结器但不会释放该对象。对象本身只会在下一个 GC 周期被释放——浪费内存。总而言之,您看起来像是在尝试实现析构函数。请不要:让你的对象实现被调用的那种标准方法,Close并在你的类型的契约中声明程序员在完成对象时需要调用它。当程序员无论如何都想调用这样的方法时,他们会使用defer.请注意,这种方法非常适用于 Go stdlib 中的所有类型,这些类型包装了操作系统提供的资源——文件和套接字描述符。所以没有必要假装你的类型有什么不同。要记住的另一件有用的事情是,Go 被明确设计为严肃、简洁、没有魔法、面对面的语言,而您只是想为其添加魔法。请不要,那些喜欢解密魔法层的人会使用Scala不同的语言进行编程。
随时随地看视频慕课网APP

相关分类

Go
我要回答