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

mat*_*ull 8 destructor instance go

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

我尝试在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
}
Run Code Online (Sandbox Code Playgroud)

因为我无法通过析构函数减少计数器,所以这种方法有效.

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

Nic*_*ood 9

您可以像这样使用runtime.SetFinalizer.见这里的操场版本.

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)
}
Run Code Online (Sandbox Code Playgroud)

这打印

Entities 1 {Sausage}
Entities 2 {Potato}
Entities 0
Entities 1
Entities 0
Run Code Online (Sandbox Code Playgroud)

请注意使用Finalizer的文档

x的终结器计划在x变得无法访问后的某个任意时间运行.无法保证终结器将在程序退出之前运行,因此通常它们仅用于在长时间运行的程序期间释放与对象关联的非内存资源.


Den*_*ret 5

关于终结者的讨论是关于golang-nuts的.

目前,

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

因此,您必须自己管理实例计数.

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