如何跟踪类型实例的数量?

时间:2012-11-09 13:26:06

标签: go instance destructor

在面向对象语言中,我使用类变量来跟踪当前生成的实例数量,方法是在构造时递增并在销毁时递减。

我尝试在go中实现类似的行为:

package entity

type Entity struct {
    Name string
}

func New(name string) Entity {
    entity := Entity{name}
    counter++
    return entity
}

var counter int = 0

func (e *Entity) Count() int {
    return counter
}

并且这有效,因为我不能通过析构函数递减计数器。

我可以以某种方式模仿对象破坏吗? 如何正确跟踪实例计数?

2 个答案:

答案 0 :(得分:9)

您可以像这样使用runtime.SetFinalizer。有关游乐场版本,请参阅here

package main

import (
    "fmt"
    "runtime"
)

type Entity struct {
    Name string
}

var counter int = 0

func New(name string) Entity {
    entity := Entity{name}
    counter++
    runtime.SetFinalizer(&entity, func(_ *Entity) {
        counter--
    })
    return entity
}

func (e *Entity) Count() int {
    return counter
}

func main() {
    e := New("Sausage")
    fmt.Println("Entities", counter, e)
    e = New("Potato")
    fmt.Println("Entities", counter, e)
    runtime.GC()
    fmt.Println("Entities", counter)
    e = New("Leek")
    fmt.Println("Entities", counter)
    runtime.GC()
    fmt.Println("Entities", counter)
}

打印

Entities 1 {Sausage}
Entities 2 {Potato}
Entities 0
Entities 1
Entities 0

请注意使用Finalizer的文档

  

x的终结器计划在x后的任意时间运行   变得无法到达。无法保证终结器能够运行   在程序退出之前,通常它们仅对于有用   在a期间释放与对象关联的非内存资源   长期运行的计划。

答案 1 :(得分:5)

关于终结者,有一个discussion关于golang-nuts。

目前,

  • 没有终结器功能(编辑:没有可靠的终结器功能,如Nick所示)
  • GC不使用且不保留任何引用计数

所以你必须自己管理你的实例计数。

通常情况下,您没有自己的实例,因此对于许多实际用途(不包括复杂且难以理解的程序的剖析),您可以使用defer来跟踪生命的终结。你的变量。我不会假装这真的取代了终结者,但它很简单而且经常足够。