欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang 基礎之函數(shù)使用(匿名遞歸閉包)實例詳解

 更新時間:2023年10月19日 10:49:04   作者:帽兒山的槍手  
這篇文章主要為大家介紹了Golang 基礎之函數(shù)使用(匿名遞歸閉包)實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

匿名函數(shù)

在Go語言中,函數(shù)可以像普通變量一樣被傳遞或使用,支持隨時在代碼里定義匿名函數(shù)。

匿名函數(shù)由一個不帶函數(shù)名的函數(shù)聲明和函數(shù)體組成。匿名函數(shù)的優(yōu)越性在于可以直接使用函數(shù)內(nèi)的變量,不必申明。

匿名函數(shù)有動態(tài)創(chuàng)建的特性,該特性使得匿名函數(shù)不用通過參數(shù)傳遞的方式,就可以直接引用外部的變量。

使用

第一種用法:將匿名函數(shù)賦給變量,在通過變量調(diào)用匿名函數(shù)

sum := func(a, b int) int {
  return a + b
}
fmt.Println(sum(1, 2)) // 輸出 3

第二種用法:在定義匿名函數(shù)的時候直接使用,這種方式只能使用一次傳參

sum := func(a, b int) int {
    return a + b
}(1,2) // 傳入?yún)?shù)
fmt.Println(sum) // 輸出 3

第三種用法:將匿名函數(shù)賦給一個全局變量,匿名函數(shù)在當前程序中都可以使用

package main
import "fmt"
var (
  // 全局變量必須首字母大寫
    Sum = func(a, b int) int {
        return a + b
    }
)
func main() {
    sum := Sum(1, 2)
    fmt.Println("sum=", sum) // 輸出 sum= 3
}

閉包

所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環(huán)境的表達式(通常是一個函數(shù)),因而這些變量也是該表達式的一部分。

閉包(Closure),是引用了自由變量的函數(shù)。這個被引用的自由變量將和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說法認為閉包是由函數(shù)和與其相關的引用環(huán)境組合而成的實體。閉包在運行時可以有多個實例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實例。

可以理解為:閉包是匿名函數(shù)與匿名函數(shù)所引用環(huán)境的組合,類似常規(guī)函數(shù)引用全局變量處于一個包的環(huán)境。

閉包的優(yōu)點

  • 變量可以常駐內(nèi)存
  • 變量不污染全局

閉包里作用域返回的局部變量不會被立刻銷毀回收,可能會占用更多內(nèi)存過度使用閉包會導致性能下降。

使用

package main
import "fmt"
func main() {
    n := 0
    count := func() int {  // 這就是一個閉包
        n += 1
        return n
    }
    fmt.Println(count()) // 輸出 1
    fmt.Println(count()) // 輸出 2
}

常規(guī)函數(shù)、匿名函數(shù) + 全局變量 + 包就等同于閉包, count不僅存儲了函數(shù)的返回值,還存儲了閉包的狀態(tài)。

閉包被返回賦予一個同類型的變量時,同時賦值的是整個閉包的狀態(tài),該狀態(tài)會一直存在外部被賦值的變量count中,直到count被銷毀,整個閉包生命周期結束。

也可以寫成下列形式

package main
import "fmt"
func Count() func() int { // 返回函數(shù)
    n := 0
    return func() int {
        n++
        return n
    }
}
func main() {
    count := Count()
    fmt.Println(count()) // 輸出 1
    fmt.Println(count()) // 輸出 2
}

高級閉包特性,比如并發(fā)中的閉包。 將放到后面章節(jié)為大家介紹。

遞歸函數(shù)

遞歸,就是在運行的過程中調(diào)用自己。

一個函數(shù)調(diào)用自己, 就叫做遞歸函數(shù)。

構成遞歸具備的條件:

  • 子問題需要與原始問題為同樣的事,且更為簡單。
  • 不能無限制地調(diào)用本身,須有個出口,化簡為非遞歸狀況處理。

使用

舉例:數(shù)字階乘

一個正整數(shù)的階乘是所有小于及等于該數(shù)的正整數(shù)的積,并且0的階乘為1。

package main
import "fmt"
func factorial(i int) int {  // 解讀為 5*4*3*2*1=120 
    if i <= 1 {
        return 1
    }
    return i * factorial(i-1)
}
func main() {
    var i int = 5
    fmt.Printf("%d\n", factorial((i))) // 120
}
1808年,基斯頓·卡曼引進這個表示法。

舉例:裴波那契數(shù)列(Fibonacci)

這個數(shù)列從第3項開始,每一項都等于前兩項之和。

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)) // 0 1 1 2 3 5 8 13 21 34
    }
}

延遲調(diào)用 (defer)

在基礎語法中已經(jīng)介紹了defer延遲調(diào)用的使用,今天深入了解使用一下defer機制。

defer特性

  • 關鍵字 defer 用于注冊延遲調(diào)用。
  • 這些調(diào)用直到 return 前才被執(zhí)。因此,可以用來做資源清理。
  • 多個defer語句,按先進后出的方式執(zhí)行。
  • defer語句中的變量,在defer聲明時就決定了。
  • 某個延遲調(diào)用發(fā)生錯誤,這些調(diào)用依舊會被執(zhí)行。

defer后面的語句在執(zhí)行的時候,函數(shù)調(diào)用的參數(shù)會被保存起來,但是不執(zhí)行。也就是復制了一份。

defer用途

  • 關閉文件句柄
  • 鎖資源釋放
  • 數(shù)據(jù)庫連接釋放

使用

多個 defer 注冊,按 FILO 次序執(zhí)行 ( 先進后出 ) 原則。

package main
func main() {
    defer println("1") // 先進來, 最后出去
    defer println("2")
    defer println("3") // 最后進來, 先出去
}

輸出

3
2
1

延遲調(diào)用參數(shù)在注冊時求值或復制,可以用指針或閉包 “延遲” 讀取。

package main

import "fmt"

func main() {
    x, y := 10, 100
    defer func(i int) {
        fmt.Printf("defer x = %v, y = %v\n", i, y) // y 閉包引用
    }(x) // x 被復制

    x += 10
    y += 20
    println("x = ", x, "y = ", y)
}

輸出

x =  20 y =  120
defer x = 10, y = 120

defer和return兩者執(zhí)行順序

  • 有名返回值 (函數(shù)返回值為已經(jīng)命名的返回值)
package main
import "fmt"
func foo() (i int) { // 3.return i 值
    i = 0
    defer func() {
    fmt.Println(i) // 2.讀取臨時變量地址(返回值)
    }()
    return 2 // 1.返回值賦值,寫入臨時變量
}
func main() {
    foo()
}

輸出

2

在 foo() 返回值的函數(shù)中 (這里返回值為 i),執(zhí)行 return 2 的時候?qū)嶋H上已經(jīng)將i 的值重新賦值為2。 所以defer closure輸出結果為2。

解析:

return 的機制:1.首先將返回值放到一個臨時變量中(為返回值賦值) 2. 然后將返回值返回到被調(diào)用處。

而defer函數(shù)恰在return的兩個操作之間執(zhí)行。

執(zhí)行順序是: 先為返回值賦值,即將返回值放到一個臨時變量中,然后執(zhí)行defer,然后return到函數(shù)被調(diào)用處。

  • 無名返回值 (即函數(shù)返回值為沒有命名的函數(shù)返回值)
package main
import "fmt"
func foo() int {
    var i int
    defer func() {
        i++ // 這個地方 i,不是臨時變量
        fmt.Println("defer = ", i) // 輸出 defer = 1
    }()
    return i // 返回值賦值,寫入臨時變量
}
func main() {
    fmt.Println("return = ", foo()) // 輸出 return = 0
}

 解析:return 先把返回值放到一個臨時變量中,defer函數(shù)無法獲取到這個臨時變量地址 (沒有函數(shù)返回值),所以無論defer函數(shù)做任何操作,都不會對最終返回值造成任何變動。

以上就是Golang 基礎之函數(shù)使用(匿名遞歸閉包)實例詳解的詳細內(nèi)容,更多關于Golang 匿名遞歸函數(shù)閉包的資料請關注腳本之家其它相關文章!

相關文章

最新評論