golangの基礎--deferを詳しく話します

3035 ワード

defer匿名関数特性
  • の実行は、他の言語の構造関数と同様であり、関数体の実行が終了すると、呼び出し順の に従って
    //      
    package main
    import "fmt"
    
    func main() {
    	fmt.Println("a")
    	defer fmt.Println("b")
    	defer fmt.Println("c")
    }
    /*  
    a
    c
    b
    */
    
  • が1つずつ実行する.
  • 関数が発生しても はtryと同様に実行されます...except
  • は、リソースのクリーンアップ、ファイルのクローズ、ロック解除、記録時間などの操作
  • によく使用される.
  • 匿名関数の呼び出しをサポートする
  • 匿名関数と組み合わせることでreturn後に関数計算を修正できる結果-関数内の変数がdefer時の匿名関数のパラメータである場合、deferを定義する際にコピーが取得され、そうでない場合、変数のアドレス
    //      
    package main
    import "fmt"
    
    func main() {
    	for i := 0; i < 3; i++ {
    		defer func() { //          defer    
    			fmt.Println(i) //        i   
    		}()
    	}
    }
    
    /*  
    3
    3
    3
    */
    
  • が参照される.
  • Goには異常メカニズムはありませんが、エラー
  • を処理するためにpanic/recoverモードがあります.
  • Panicはどこでも開始できます
    panicエラーメカニズム
    //panic     ,  panic   ,       
    package main
    import "fmt"
    func main() {
    	A()
    	B()
    	C()
    }
    
    func A() {
    	fmt.Println("func a")
    }
    
    func B() {
    	panic("Panic B")
    }
    func C() {
    	fmt.Println("func")
    }
    
    /*  
    A()-->	func a
    B()--->	panic: Panic B
    ---------------
    	goroutine 1 [running]:
    	main.B()
    C()		C:/Users/faily/Desktop/workspace/src/defer1.go:17 +0x40
    	main.main()
    		C:/Users/faily/Desktop/workspace/src/defer1.go:8 +0x2c
    	exit status 2
    	exit status 1
    */
    
  • deferは、recoverおよび匿名関数処理プログラムに現れる重大なエラー(panic文)に合わせてプログラムエラーを呼び出し、python言語におけるtry...except,finally文に類似した実行を継続する.
    //defer,recover  ,  panic     
    package main
    import "fmt"
    
    func main() {
    	A()
    	B()
    	C()
    }
    
    func A() {
    	fmt.Println("func a")
    }
    func B() {
    	defer func() { 				            //defer    panic  
    		if err := recover(); err != nil { 	    //  recover  (      panic  ),   
    			fmt.Println("Recover in B")  //      panic,  err  nil(    )
    		} 
    	}()							    //  ,defer            ()								
    	panic("Panic B") 				   //      ,       。
    
    }
    func C() {
    	fmt.Println("func C")
    
    }
    
    /*  
    A()-->	func a
    B()-->	Recover in B
    C()-->	func C
    */ 
    

  • -defer、匿名関数、変数伝達、配列array、forループ統合>次のコードを実行し、出力結果を分析します.
    ```go
    package main
    import "fmt"
    func main() {
    var fs = [4]func(){}  //      fs,       ,            func
    for i := 0; i < 4; i++ {
    	defer fmt.Println("defer i=", i) //defer,        ,  for  ,       ,i    ,    
    	defer func() { fmt.Println("defer closure i=", i) }()   // i      defer     ,            ,      i     (    i    )
    	fs[i] = func() { fmt.Println("closure i=", i) }   // fs      ,i              ,  i    i     (    i    )
    	fmt.Println(i)
    }
    for n, f := range fs {                // for     ,       (    )
    	fmt.Println(n)
    	f()
    }
    }
    /*  
    n=0
    	closure i= 4		
    n=1
    	closure i= 4
    n=2
    	closure i= 4
    n=3
    	closure i= 4
    ------------------------
    defer closure i= 4		
    defer i= 3				
    defer closure i= 4
    defer i= 2
    defer closure i= 4
    defer i= 1
    defer closure i= 4
    defer i= 0
    */
    ```
    

    解析結果、詳細はコードコメントを参照