GO匿名関数とクローズド


匿名関数:名前の通り名前のない関数です。java、js、phpなど多くの言語があります。その中でjsが一番好きです。匿名関数の最大の用途は、データ汚染を避けるためにブロックレベルのスコープをシミュレートすることである。
今日は主にGolang言語の匿名関数とクローズドについて話します。
匿名関数
例:
1、
package main

import (
   "fmt"
)
func main() {
   f:=func(){
      fmt.Println("hello world")
   }
   f()//hello world
   fmt.Printf("%T
", f) // func() }
2、パラメータ付き
package main

import (
   "fmt"
)
func main() {
   f:=func(args string){
      fmt.Println(args)
   }
   f("hello world")//hello world
   // 
   (func(args string){
        fmt.Println(args)
    })("hello world")//hello world
    // 
    func(args string) {
        fmt.Println(args)
    }("hello world") //hello world
}
3、戻り値付き
package main

import "fmt"

func main() {
   f:=func()string{
      return "hello world"
   }
   a:=f()
   fmt.Println(a)//hello world
}
4、複数の匿名関数
package main

import "fmt"

func main() {
   f1,f2:=F(1,2)
   fmt.Println(f1(4))//6
   fmt.Println(f2())//6
}
func F(x, y int)(func(int)int,func()int) {
   f1 := func(z int) int {
      return (x + y) * z / 2
   }

   f2 := func() int {
      return 2 * (x + y)
   }
   return f1,f2
}
クローズド(closure)
パッケージを閉じます。つまり関数のネストです。内部の関数は外層関数のすべての変数を使ってもいいです。外層関数はすでに実行済みです。
例:
1、
package main

import "fmt"

func main() {
    a := Fun()
    b:=a("hello ")
    c:=a("hello ")
    fmt.Println(b)//hello world
    fmt.Println(c)//worldhello hello 
}
func Fun() func(string) string {
    a := "world"
    return func(args string) string {
        a += args
        return  a
    }
}
2、
package main

import "fmt"

func main() {
   a := Fun()
   d := Fun()
   b:=a("hello ")
   c:=a("hello ")
   e:=d("hello ")
   f:=d("hello ")
   fmt.Println(b)//hello world
   fmt.Println(c)//worldhello hello
   fmt.Println(e)//hello world
   fmt.Println(f)//worldhello hello
}
func Fun() func(string) string {
   a := "world"
   return func(args string) string {
      a += args
      return  a
   }
}
注意F()を2回呼び出すと、同じa変数ではないように維持されます。
3、
package main

import "fmt"

func main() {
   a := F()
   a[0]()//0xc00004c080 3
   a[1]()//0xc00004c080 3
   a[2]()//0xc00004c080 3
}
func F() []func() {
   b := make([]func(), 3, 3)
   for i := 0; i < 3; i++ {
      b[i] = func() {
         fmt.Println(&i,i)
      }
   }
   return b
}
クローズドは、参照によって外部関数の変数を使用します。例では一度の関数Fのみが呼び出され、一つのクローズドパケットを構成し、iは外部関数Bで定義されるので、この変数iはクローズドで維持され、a[0]、a[1]、a[2]のiはすべてクローズド中iの参照である。したがって、iの値はすでに3になっていますので、a[0]()を呼び出した場合の出力は0ではなく3です。
4、上記のバグを避けるには、以下の方法で上記の例と比較するように注意してください。
package main

import "fmt"

func main() {
    a := F()
    a[0]() //0xc00000a0a8 0
    a[1]() //0xc00000a0c0 1
    a[2]() //0xc00000a0c8 2
}
func F() []func() {
    b := make([]func(), 3, 3)
    for i := 0; i < 3; i++ {
        b[i] = (func(j int) func() {
            return func() {
                fmt.Println(&j, j)
            }
        })(i)
    }
    return b
}
  
package main

import "fmt"

func main() {
    a := F()
    a[0]() //0xc00004c080 0
    a[1]() //0xc00004c088 1
    a[2]() //0xc00004c090 2
}
func F() []func() {
    b := make([]func(), 3, 3)
    for i := 0; i < 3; i++ {
        j := i
        b[i] = func() {
            fmt.Println(&j, j)
        }
    }
    return b
}
各動作は、匿名関数を配列に入れるだけで実行されず、参照変数はiであり、iの変更に伴い、匿名関数のiも変化しているので、これらの関数を実行すると、環境変数iの最後の値が読み取られる。解決策は、複製変数iのたびに、次いで匿名関数に送られて、クローズドされた環境変数が異なるようにすることである。
5、
package main

import "fmt"

func main() {
   fmt.Println(F())//2
}
func F() (r int) {
   defer func() {
      r++
   }()
   return 1
}
出力結果は2です。つまり、r=1を先に実行して、r++を実行します。
6、再帰関数
もう一つの場合は、全部を使って閉じなければならないということです。つまり、再帰関数です。
package main

import "fmt"

func F(i int) int {
   if i <= 1 {
      return 1
   }
   return i * F(i-1)
}

func main() {
   var i int = 3
   fmt.Println(i, F(i))// 3 6
}
7、フィボナッチ数列(フィボナッチ)
この数列は第3項から始まります。各項目は前の2項の合計に等しいです。
package main

import "fmt"

func fibonaci(i int) int {
    if i == 0 {
        return 0
    }
    if i == 1 {
        return 1
    }
    return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    var i int
    for i = 0; i < 10; i++ {
        fmt.Printf("%d
", fibonaci(i)) } }
リボン:
匿名関数とクローズドは同じです。匿名関数はクローズドです。匿名関数はプログラミングに柔軟性を与え、バグも発生しやすく、関数のパラメータや受け入れ可能なパラメータに注意する必要があります。
links
  • ディレクトリ