go語言學習筆記12------函數④

1.匿名函數與閉包

1.1匿名函數

前面我們定義函數的時候,發現是不能在一個函數中,再次定義一個函數。如果我們想在一個函數中再定義一個函數,那麼可以使用匿名函數,所謂匿名函數就是沒有名字的函數。
如下所示:

package main

import "fmt"

func main() {
   var num int
   num=9
   f:=func(){
      num++
      fmt.Println(num)
   }
   f()
   fmt.Println(num)
}

在main( )函數中定義了一個匿名函數,定義的方式非常簡單func(){ 函數體 }, 一定要注意的是在func的後面沒有函數的名字,同時在這裏定義的該匿名函數也沒有參數。我們將定義好的匿名函數賦值給了變量f,那麼變量f就是一個函數類型。要想執行該匿名函數,就可以通過f( )的方式去調用執行。
在這裏,有一件非常有意思的事情,就是在匿名函數中可以直接訪問main( )函數中定義的局部變量,並且在匿名函數中對變量的值進行了修改,最終會影響到整個main( )函數中定義的變量的值。

ackage main

import "fmt"

func main() {
   var num int
   num=9
   f:=func(){
      num++
      fmt.Println("匿名函數",num)
   }
   type functype func()
   var f1 functype
   f1=f
   f1()
   fmt.Println("main函數",num)
}

上面案例中,定義的匿名函數賦值給了變量f,那麼f的類型就是函數類型,所以我們自己也可以定義一個函數類型的變量來調用匿名函數。但是上面的應用比較繁瑣,實際用的比較少。

下面看一下怎樣給匿名函數傳遞參數,並且匿名函數如果有返回值,並接收處理:

package main

import "fmt"

func main() {
x,y:=func(i,j int)(max,min int){
   if i>j{
      max=i
      min=j
   }else{
      max=j
      min=i
   }
   return
}(30,59)
fmt.Println(x,y)
}

以上案例中定義了一個匿名函數,該匿名函數需要兩個整型參數,同時指定了該函數返回值的名字是變量max與min
當執行到return時,讓變量manx與min返回,賦值了變量x,y。x中存儲的是max變量的值,y中存儲的是min變量的值。

以上就是關於什麼是匿名函數,以及匿名函數的使用。匿名函數最主要的功能就是實現了閉包。

1.2閉包

所謂的閉包是指有權訪問另一個函數作用域中的變量的函數,就是在一個函數內部創建另一個函數。
在Go語言裏,所有的匿名函數(Go語言規範中稱之爲函數字面量)都是閉包。
根據以上定義,那麼上一節定義的匿名函數其實就是閉包。(仔細體會上一節定義的匿名函數)
(也可以這樣理解閉包:雖然不能在一個函數裏直接聲明另一個函數,但是可以在一個函數中聲明一個函數類型的變量,此時的函數稱爲閉包(closure))

下面我們通過一個案例,看一下關於閉包的應用。
思考:以下程序執行的結果是:

package main

import "fmt"

func test() int {
   var x int
   x++
   return x
}
func main() {
   fmt.Println(test())
   fmt.Println(test())
   fmt.Println(test())
}

雖然Test( )函數調用了三次,但是輸出都是1.原因是:
每次調用Test( )函數,都是重新聲明變量x,當函數執行完成後,x會自動被釋放所佔資源。
如果想實現累加運算,這裏就需要用到閉包(匿名函數)。

package main

import "fmt"

func test() func()int{
   var x int
   return func()int{
      x++
      return x
   }
}
func main() {
       f:=test()
   fmt.Println(f())
   fmt.Println(f())
   fmt.Println(f())
}

由於在定義Test( )函數時指定了返回的類型是一個匿名函數,並且該匿名函數返回的類型是整型。
所以在Test( )函數中定義了一個匿名函數,並且將整個匿名函數返回,匿名函數返回的是整型。
在main( )函數中定義了一個變量f,該變量的類型是匿名函數,f( )表示調用執行匿名函數。
最終執行完成後發現,實現了數字的累加。
因爲匿名函數(閉包),有一個很重要的特點:
它不關心這些捕獲了的變量和常量是否已經超出了作用域,所以只有閉包還在使用它,這些變量就還會存在。

2.遞歸函數

如果一個函數在內部不調用其它的函數,而是自己本身的話,這個函數就是遞歸函數。
例如:

package main

import "fmt"

func test(a int) {
   if a==1{
      fmt.Println("a=",a)
      return
   }
   test(a-1)
   fmt.Println("a1=",a)
}
func main() {
     test(3)
}

舉個例子,我們來計算階乘 n! = 1 * 2 * 3 * … * n

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章