Go adalah bahasa dengan manajemen memori otomatis: pengumpul sampah, tanpa membutuhkan programmer, menangani pemulihan memori yang digunakan oleh objek yang tidak lagi digunakan oleh program. Tetapi semua otomatisasi secara keseluruhan dibatasi oleh memori - kita masih perlu menjaga sumber daya lainnya yang digunakan oleh program itu sendiri.
, - , runtime.SetFinalizer. , , . Go - , , , , .
res1, err := NewResource1()
if err != nil {
return nil, err
}
res2, err := NewResource2(res1)
if err != nil {
res1.Close()
return nil, err
}
res3, err := NewResource3(res2)
if err != nil {
res2.Close()
res1.Close()
return nil, err
}
v, err := res3.DoSomething()
if err != nil {
res3.Close()
res2.Close()
res1.Close()
return nil, err
}
res3.Close()
res2.Close()
res1.Close()
return v, nil
. , C# Java using statement try-with-resources statement . Go , , defer statement. , :
res1, err := NewResource1()
if err != nil {
return nil, err
}
defer res1.Close()
res2, err := NewResource2(res1)
if err != nil {
return nil, err
}
defer res2.Close()
res3, err := NewResource3(res2)
if err != nil {
return nil, err
}
defer res3.Close()
return res3.DoSomething()
Close . Close - .
, . - defer . , , - , . , , . , , - , - - , (, main), , , , , .
, Wire. ( Wire) . . cleanup function, . .
Dedicated finalization
, c cleanup function, Wire, . , Close ( ) :
;
.
, , , . , Go :
res, cleanup, err := NewResource()
if err != nil {
return err
}
// cleanup, .
if err := res.DoSomething(); err != nil {
return err
}
, (, ) ( ) . , " ", , , "" "" , .
Composite finalization
defer (, ), :
func Finalize(finalizers ...func()) {
// .
for i := len(finalizers) - 1; i >= 0; i-- {
func() {
defer func() {
// , .
// multierror :
// 1) ;
// 2) .
recover()
}()
finalizers[i]()
}()
}
}
func NewResource3() (*Resource3, func(), error) {
var (
finalizers []func() //
successful bool //
)
defer func() {
// ,
// -
// .
if !successfull {
Finalize(finalizers...)
}
}()
res1, fin1, err := NewResource1()
if err != nil {
return nil, nil, err
}
finalizers = append(finalizers, fin1)
res2, fin2, err := NewResource2(res1)
if err != nil {
return nil, nil, err
}
finalizers = append(finalizers, fin2)
res3 := &Resource3{
resource2: res2,
}
fin3 := func() {
Finalize(finalizers...)
}
// .
//
// .
successful = true
return res3, fin3, nil
}
Finalize - .
new - error - defer , , , , .
KDone
Saya telah memposting pustaka KDone yang menyediakan seperangkat alat di atas. Dia adalah bagian dari proyek Kata , yang akan dibahas selanjutnya. Kita dapat berasumsi bahwa saat ini API-nya stabil dan jika berubah, itu tidak akan signifikan - meskipun demikian, pustaka tersebut masih baru dan saya masih menggunakan versi nol utama jika terjadi perubahan yang tidak terduga.
Konstruktor tipikal yang menggunakan pustaka ini terlihat seperti ini:
func NewResource(...) (res Resource, dtor kdone.Destructor, err error) {
defer kerror.Catch(&err) //
// KError.
// .
reaper := kdone.NewReaper() // reaper.
defer reaper.MustFinalize() //
// .
// ... reaper.MustAssume(dtor) ... // reaper
//
// .
return res, reaper.MustRelease(), nil // reaper
//
// .
}
Bagaimana menurut anda? Konsepnya cukup sederhana, tetapi mungkin saya melewatkan sesuatu dalam penalaran saya? Atau apakah Anda punya saran untuk perbaikan? Saya akan senang berdiskusi di komentar.