2012-11-09 11 views
8

In objektorientierten Sprachen verwende ich Klassenvariablen, um zu verfolgen, wie viele Instanzen derzeit generiert werden, indem bei der Konstruktion inkrementiert und bei der Zerstörung dekrementiert wird.Wie protokolliere ich die Anzahl der Instanzen eines Typs?

Ich versuche, ein ähnliches Verhalten in gehen zu implementieren:

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 
} 

und das funktioniert auf halbem Weg, wie ich den Zähler nicht über eine destructor verringern kann.

Kann ich die Objektzerstörung irgendwie nachahmen? Wie würde ich die Anzahl der Instanzen korrekt verfolgen?

+0

Gibt es eine eingebaute Methode, um die Referenzzählung für ein Objekt anzuzeigen? –

Antwort

9

Sie können runtime.SetFinalizer so verwenden. Siehe here für Spielplatzversion.

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) 
} 

Dieser druckt

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

Hinweis Diese von der Dokumentation für gotchas mit Finalizer

Die Finalizerthread für x geplant ist, bei einer beliebigen Zeit zu laufen, nachdem x nicht mehr erreichbar ist. Es gibt keine Garantie dafür, dass Finalizer ausgeführt werden, bevor ein Programm beendet wird, so dass sie normalerweise nur für nützlich sind, die Nichtspeicherressourcen freigeben, die einem Objekt während eines lang laufenden Programms zugeordnet sind.

+0

+1 Ich lag falsch, da ich diese neue Funktion nicht gesehen hatte –

5

Es gab eine discussion auf Golang-Nüsse über Finalizer.

jetzt Denn

  • gibt es keine Finalizerthread Funktion (edit: keine verlässliche Finalizerthread Funktion, wie mir von Nick gezeigt wurde)
  • verwenden die GC nicht und nicht aufrechterhalten Jede Referenzzählung

Sie müssen also Ihre Instanzzählung selbst verwalten.

Normalerweise haben Sie keine Instanzen auf sich selbst, so dass Sie für viele praktische Anwendungen (ohne das Profiling eines komplexen und schwer verständlichen Programms) defer verwenden können, um das Ende der Lebensdauer Ihrer Variablen zu verfolgen. Ich werde nicht so tun, als ob Finalizer wirklich ersetzt, aber es ist einfach und oft ausreichend.

Verwandte Themen