GOのリソースを解放する

Goは、自動メモリ管理を備えた言語です。ガベージコレクターは、プログラマーを必要とせずに、プログラムで使用されなくなったオブジェクトで使用されているメモリの再利用を処理します。しかし、全体としてのすべての自動化はメモリによって制限されます-プログラムによって使用される残りのリソースを自分で処理する必要があります。





画像ソース:http://kenimation.net/doctor-who%E2%80%AC-dalek/
画像ソース:http://kenimation.net/doctor-who%E2%80%AC-dalek/

, - , 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
      
      



, . , ( ). Close , - .





. , 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

上記のツールセットを提供するKDoneライブラリ投稿しました彼女は、次に説明するカタプロジェクトの一部です現時点では、APIは安定しており、変更されても重要ではないと想定できます。それでも、ライブラリはまだ新鮮であり、予期しない変更が発生した場合に備えて、メジャーバージョンはゼロのままです。





このライブラリを使用する一般的なコンストラクタは次のようになります。





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  
                                         //      
                                         //  .
}
      
      



どう思いますか?コンセプトは簡単ですが、推論で何かを逃したのではないでしょうか。または、改善のための提案がありますか?コメントで議論していただければ幸いです。








All Articles