Golang閉パッケージの典型的な応用

10385 ワード

概要:


参考ブログ:
  • https://www.calhoun.io/5-useful-ways-to-use-closures-in-go/

  • データの分離


    このようにして、呼び出し者のデータを隔離し、指定した結果を出力することができる.あるいは、関数呼び出しの回数を計算したい場合があります.関数カウンタ:
    //  
    func counter(f func()) func() int {  
    	n := 0
    	return func() int {
    		f()
    		n += 1
    		return n
    	}
    }
    
    //  
    func foo() {
    	fmt.Println("call foo")
    }
    
    func main() {
    	cnt := counter(foo)
    	cnt()
    	cnt()
    	cnt()
    	fmt.Println(cnt())
    }
    /*
     :
    call foo
    call foo
    call foo
    call foo
    4
    */
    
    counter任意の入力値と戻り値が空の関数を受け入れ、同時に1つの閉パケットを返すことができ、ここで閉パケットの結果は関数の呼び出し回数である.この例では、cnt閉パケットへの参照が終了するまで、閉パケットが破棄されない.1つの閉パケットは、外部参照がない場合にのみ、ステータスとともに破棄されます.パラメータを必要とする関数を記録する場合は、counter渡すパラメータタイプを個別に渡す必要があります.
    フィボナッチ数列:
    func makeFibGen() func() int {
    	f1 := 0
    	f2 := 1
    	return func() int {
    		f2, f1 = f1+f2, f2
    		return f1
    	}
    }
    
    func main() {
    	gen := makeFibGen()
    	for i := 0; i < 10; i++ {
    		fmt.Println(gen())
    	}
    }
    /*
     :
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    */
    

    コード理解:makeFibGen()は、フィボナッチ数列が何番目に実行されたかを示す閉パケットであり、閉パケットが与えられた結果はi項数列の結果である.

    関数の装飾とミドルウェアの作成


    関数はGo言語の一等公民であり,関数のパラメータとして伝達することができる.アクセサリーやミドルウェアとは,関数がパラメータとして伝達される場合を指す.
    func wrapping(f func() string) {
    	fmt.Println("do my work...")
    	fmt.Println("wrapping function: ", f())
    	fmt.Println("my work finished !")
    }
    
    func sayHello() string {
    	return "Hello !"
    }
    
    func sayByeBye() string {
    	return "Bye Bye !"
    }
    
    func main() {
    	wrapping(sayHello)
    	wrapping(sayByeBye)
    }
    /*
     :
    do my work...
    wrapping function:  Hello !
    my work finished !
    do my work...
    wrapping function:  Bye Bye !
    my work finished !
    */
    

    1つの関数は、伝達された異なる関数に基づいて異なる反応を生成することができ、伝達された関数は本質的に閉パケットである.

    Defer Work


    このプロセスは主にJavascriptのコールバック関数と比較されます.例えば、JSでは次のようになります.
    doWork1(a, b, function(result) {
      doWork2(result, function(result) {
        doWork3(result, function(result) {
          // use the final result here
        });
      });
    });
    console.log("hi!");
    
    doWork1関数コールバックdoWork2、そしてdoWork2関数コールバックdoWork3、実行順はdoWork1->doWork2->doWork3がありますが、次の関数は前の関数の状態にして、前の関数の処理結果に応じた処理が必要です.
    Go言語では、閉パッケージを直接使用して解決します.
    go func() {
      result := doWork1(a, b)
      result = doWork2(result)
      result = doWork3(result)
      // Use the final result
    }()
    fmt.Println("hi!")
    

    閉パッケージは、プログラムの実行状態をよく保存し、プログラムの論理をより明確にすることができます.