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

Go 中的终结器测试

Go 中的终结器测试

Go
ITMISS 2021-10-18 14:10:08
有没有办法合理地编写测试用例来测试终结器行为?我正在尝试在 Go 中实现一个内存敏感的规范化映射/缓存。由于没有“软引用”的概念(并且因为我的对象图将始终形成一个 DAG),因此我使用一个跟踪用户空间中引用计数的微小界面/框架来完成此操作:type ReferenceCounted interface {   RefCount() int   IncRef()   DecRef() (bool, error)}type Finalizable interface {   ReferenceCounted   Finalize()}type AbstractCounted struct {     // unexported fields}它的工作方式是你有一个嵌入 AbstractCounted 的结构,并实现Finalizable.Finalize()- 这些一起使该结构接收Finalizable接口。然后有一个函数func MakeRef(obj Finalizable) *Reference返回一个指向结构的指针,该结构接收一个方法func Get() Finalizable,它获取引用目标,并通过增加底层对象的引用计数来初始化它,然后设置一个终结器(via runtime.SetFinalizer())来减少引用。 AbstractCounted的Finalizable实现反过来调用Finalize()结构,当引用计数达到零时嵌入它。所以,一切都被设置得非常像 Java 中的软引用/引用队列,除了它是引用计数,而不是根植于活动词法范围的标记/扫描,它可以“软”地找到可访问的东西。看起来效果很好!但是 - 我想写一个测试用例......我完全理解终结器调用被推迟,并且不保证按照reflect包文档运行它们。在其他具有运行时 gc 和终结器(C#、VB、Java、Python 等)的语言中,情况也是如此。但是,在所有其他语言中,请求显式 GC(此处通过runtime.GC()函数)似乎确实会导致终结器运行。由于在 Go 中不是这种情况,我无法想出一种方法来编写将触发终结器的测试用例。是否有任何技巧或代码片段(我认为这取决于当前的实现,即可能在未来中断!)可以可靠地触发这些终结器,以便我可以编写我的测试?
查看完整描述

1 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

您无法显式触发终结器,因此您可以管理的最佳方法是确保 GC 以 启动runtime.GC(),并等待终结器运行。


如果您查看runtime/mfinal_test.go,有一些测试通过通道等待终结器调用:


runtime.SetFinalizer(y, func(z *objtype) { fin <- true })

runtime.GC()

select {

case <-fin:

case <-time.After(4 * time.Second):

    t.Errorf("finalizer of next string in memory didn't run")

}


查看完整回答
反对 回复 2021-10-18
  • 1 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信