2012-11-09 9 views
8

In linguaggi orientati agli oggetti uso variabili di classe per tenere traccia di quante istanze sono attualmente generati incrementando la costruzione e decrementando la distruzione.Come tenere traccia del conteggio delle istanze di un tipo?

cerco di implementare un comportamento simile a 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 
} 

e che funziona a metà strada come non riesco a decrementare il contatore tramite un distruttore.

Posso in qualche modo imitare la distruzione dell'oggetto? Come faccio a tenere traccia del conteggio delle istanze correttamente?

+0

Esiste un metodo integrato per mostrare il conteggio dei riferimenti su un oggetto? –

risposta

9

È possibile utilizzare runtime.SetFinalizer come questo. Vedi here per la versione di gioco.

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

Questo stampa

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

Nota questo dalla documentazione per trucchi con finalizzatori

il finalizzatore per x è pianificata l'esecuzione in un momento arbitrario dopo x diventa irraggiungibile. Non è garantito che i finalizzatori eseguano prima che un programma venga chiuso, quindi in genere sono utili solo per che rilascia risorse non di memoria associate a un oggetto durante un programma a esecuzione parziale .

+0

+1 Mi sono sbagliato perché non avevo visto questa nuova funzione –

5

C'era un discussion su golang-nuts sui finalizzatori.

Per ora,

  • non c'è alcuna funzione finalizzatore (edit: nessuna funzione finalizzatore affidabile, come è stato dimostrato a me da Nick)
  • il GC non usa e non mantiene qualsiasi numero di riferimento

Quindi è necessario gestire il conteggio dell'istanza.

Di solito, non si dispone di istanze che vivono su se stesse, quindi per molti usi pratici (non incluso il profilo di un programma complesso e difficile da capire), è possibile utilizzare defer per tracciare la fine della vita delle variabili. Non farò finta che questo sostituisca davvero i finalizzatori, ma è semplice e spesso sufficiente.