8

オブジェクト指向言語では、クラス変数を使用して、構築時にインクリメントし、破棄時にデクリメントすることによって、現在生成されているインスタンスの数を追跡します。

私は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
}

デストラクタを介してカウンターをデクリメントできないため、これは途中で機能します。

どういうわけかオブジェクトの破壊を模倣できますか?インスタンス数を正しく追跡するにはどうすればよいですか?

4

2 に答える 2

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

このプリント

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

Finalizersを使用した落とし穴のドキュメントからこれに注意してください

xのファイナライザーは、xが到達不能になった後の任意の時間に実行されるようにスケジュールされています。ファイナライザーは、プログラムが終了する前に実行される保証はありません。したがって、通常、ファイナライザーは、長時間実行されるプログラム中にオブジェクトに関連付けられた非メモリーリソースを解放する場合にのみ役立ちます。

于 2012-11-09T18:52:15.440 に答える
5

ファイナライザーについてのgolang-nutsに関する議論がありました。

今のところ、

  • ファイナライザー関数はありません(編集:ニックが私に示したように、信頼できるファイナライザー関数はありません)
  • GCは参照カウントを使用せず、維持しません

したがって、インスタンス数を自分で管理する必要があります。

通常、インスタンスは存在しないため、多くの実用的な用途(複雑で理解しにくいプログラムのプロファイリングを含まない)ではdefer、変数の寿命の終わりを追跡するために使用できます。これが実際にファイナライザーに取って代わるとは思いませんが、シンプルで多くの場合十分です。

于 2012-11-09T13:40:58.793 に答える