真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Go語言開發(fā)(六)、Go語言閉包

Go語言開發(fā)(六)、Go語言閉包

一、函數(shù)式編程

1、函數(shù)式編程簡介

函數(shù)式編程是一種編程模型,將計算機(jī)運算看作是數(shù)學(xué)中函數(shù)的計算,并且避免了狀態(tài)以及變量的概念。
在面向?qū)ο笏枷氘a(chǎn)生前,函數(shù)式編程已經(jīng)有數(shù)十年的歷史。隨著硬件性能的提升以及編譯技術(shù)和虛擬機(jī)技術(shù)的改進(jìn),一些曾被性能問題所限制的動態(tài)語言開始受到關(guān)注,Python、Ruby和Lua等語言都開始在應(yīng)用中嶄露頭角。動態(tài)語言因其方便快捷的開發(fā)方式成為很多人喜愛的編程語言,伴隨動態(tài)語言的流行,函數(shù)式編程也開始流行。

薌城網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),薌城網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為薌城1000多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請找那個售后服務(wù)好的薌城做網(wǎng)站的公司定做!

2、函數(shù)式編程的特點

函數(shù)式編程的主要特點如下:
A、變量的不可變性: 變量一經(jīng)賦值不可改變。如果需要改變,則必須復(fù)制出去,然后修改。
B、函數(shù)是一等公民: 函數(shù)也是變量,可以作為參數(shù)、返回值等在程序中進(jìn)行傳遞。
C、尾遞歸:如果遞歸很深的話,堆棧可能會爆掉,并導(dǎo)致性能大幅度下降。而尾遞歸優(yōu)化技術(shù)(需要編譯器支持)可以在每次遞歸時重用stack。

3、高階函數(shù)

在函數(shù)式編程中,函數(shù)需要作為參數(shù)傳遞,即高階函數(shù)。在數(shù)學(xué)和計算機(jī)科學(xué)中,高階函數(shù)是至少滿足下列一個條件的函數(shù):
A、函數(shù)可以作為參數(shù)被傳遞
B、函數(shù)可以作為返回值輸出

二、匿名函數(shù)

1、匿名函數(shù)簡介

匿名函數(shù)是指不需要定義函數(shù)名的一種函數(shù)實現(xiàn)方式,匿名函數(shù)由一個不帶函數(shù)名的函數(shù)聲明和函數(shù)體組成。C和C++不支持匿名函數(shù)。

func(x,y int) int {
    return x + y
}

2、匿名函數(shù)的值類型

在Go語言中,所有的函數(shù)是值類型,即可以作為參數(shù)傳遞,又可以作為返回值傳遞。
匿名函數(shù)可以賦值給一個變量:

f := func() int {
    ...
}

定義一種函數(shù)類型:
type CalcFunc func(x, y int) int
函數(shù)可以作為值傳遞:

func AddFunc(x, y int) int {
return x + y
}

func SubFunc(x, y int) int {
   return x - y
}

...

func OperationFunc(x, y int, calcFunc CalcFunc) int {
   return calcFunc(x, y)
}

func main() {
   sum := OperationFunc(1, 2, AddFunc)
   difference := OperationFunc(1, 2, SubFunc)
   ...
}

函數(shù)可以作為返回值:

// 第一種寫法
func add(x, y int) func() int {
   f := func() int {
      return x + y
   }
   return f
}

// 第二種寫法
func add(x, y int) func() int {
   return func() int {
      return x + y
   }
}

當(dāng)函數(shù)返回多個匿名函數(shù)時建議采用第一種寫法:

func calc(x, y int) (func(int), func()) {
   f1 := func(z int) int {
      return (x + y) * z / 2
   }

   f2 := func() int {
      return 2 * (x + y)
   }
   return f1, f2
}

匿名函數(shù)的調(diào)用有兩種方法:

// 通過返回值調(diào)用
func main() {
   f1, f2 := calc(2, 3)
   n1 := f1(10)
   n2 := f1(20)
   n3 := f2()
   fmt.Println("n1, n2, n3:", n1, n2, n3)
}

// 在匿名函數(shù)定義的同時進(jìn)行調(diào)用:花括號后跟參數(shù)列表表示函數(shù)調(diào)用
func safeHandler() {
   defer func() {
      err := recover()
      if err != nil {
         fmt.Println("some exception has happend:", err)
      }
   }()
   ...
}

三、閉包

1、閉包的定義

函數(shù)可以嵌套定義(嵌套的函數(shù)一般為匿名函數(shù)),即在一個函數(shù)內(nèi)部可以定義另一個函數(shù)。Go語言通過匿名函數(shù)支持閉包,C++不支持匿名函數(shù),在C++11中通過Lambda表達(dá)式支持閉包。
閉包是由函數(shù)及其相關(guān)引用環(huán)境組合而成的實體(即:閉包=函數(shù)+引用環(huán)境)。
閉包只是在形式和表現(xiàn)上像函數(shù),但實際上不是函數(shù)。函數(shù)是一些可執(zhí)行的代碼,函數(shù)代碼在函數(shù)被定義后就確定,不會在執(zhí)行時發(fā)生變化,所以一個函數(shù)只有一個實例。閉包在運行時可以有多個實例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實例。
所謂引用環(huán)境是指在程序執(zhí)行中的某個點所有處于活躍狀態(tài)的約束所組成的集合。約束是指一個變量的名字和其所代表的對象之間的聯(lián)系。由于在支持嵌套作用域的語言中,有時不能簡單直接地確定函數(shù)的引用環(huán)境,因此需要將引用環(huán)境與函數(shù)組合起來。

2、閉包的本質(zhì)

閉包是包含自由變量的代碼塊,變量不在代碼塊內(nèi)或者任何全局上下文中定義,而是在定義代碼塊的環(huán)境中定義。由于自由變量包含在代碼塊中,所以只要閉包還被使用,那么自由變量以及引用的對象就不會被釋放,要執(zhí)行的代碼為自由變量提供綁定的計算環(huán)境。
閉包可以作為函數(shù)對象或者匿名函數(shù)。支持閉包的多數(shù)語言都將函數(shù)作為第一級對象,即函數(shù)可以存儲到變量中作為參數(shù)傳遞給其它函數(shù),能夠被函數(shù)動態(tài)創(chuàng)建和返回。

func add(n int) func(int) int {
   sum := n
   f := func(x int) int {
      var i int = 2
      sum += i * x
      return sum
   }
   return f
}

add函數(shù)中函數(shù)變量為f,自由變量為sum,同時f為sum提供綁定的計算環(huán)境,sum和f組成的代碼塊就是閉包。add函數(shù)的返回值是一個閉包,而不僅僅是f函數(shù)的地址。在add閉包函數(shù)中,只有內(nèi)部的匿名函數(shù)f才能訪問局部變量i,而無法通過其它途徑訪問,因此閉包保證了i的安全性。
當(dāng)分別用不同的參數(shù)(10, 20)注入add函數(shù)而得到不同的閉包函數(shù)變量時,得到的結(jié)果是隔離的,即每次調(diào)用add函數(shù)后都將生成并保存一個新的局部變量sum。
在函數(shù)式語言中,當(dāng)內(nèi)嵌函數(shù)體內(nèi)引用到體外的變量時,將會把定義時涉及到的引用環(huán)境和函數(shù)體打包成一個整體(閉包)返回。
當(dāng)每次調(diào)用add函數(shù)時都將返回一個新的閉包實例,不同實例之間是隔離的,分別包含調(diào)用時不同的引用環(huán)境現(xiàn)場。不同于函數(shù),閉包在運行時可以有多個實例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實例。
從形式上看,匿名函數(shù)都是閉包。
函數(shù)只是一段可執(zhí)行代碼,編譯后就固定,每個函數(shù)在內(nèi)存中只有一份實例,得到函數(shù)的入口點便可以執(zhí)行函數(shù)。
對象是附有行為的數(shù)據(jù),而閉包是附有數(shù)據(jù)的行為。

3、閉包的使用

閉包經(jīng)常用于回調(diào)函數(shù),當(dāng)IO操作(例如從網(wǎng)絡(luò)獲取數(shù)據(jù)、文件讀寫)完成的時候,會對獲取的數(shù)據(jù)進(jìn)行某些操作,操作可以交給函數(shù)對象處理。
除此之外,在一些公共的操作中經(jīng)常會包含一些差異性的特殊操作,而差異性的操作可以用函數(shù)來進(jìn)行封裝。

package main

import "fmt"

func adder() func(int) int {
   sum := 0
   f := func(x int) int {
      sum += x
      return sum
   }
   return f
}

func main() {
   sum := adder()
   for i := 0; i < 10; i++ {
      fmt.Println(sum(i))
   }
}

四、閉包的應(yīng)用

package main

import "fmt"

//普通閉包
func adder() func(int) int {
   sum := 0
   return func(v int) int {
      sum += v
      return sum
   }
}

//無狀態(tài)、無變量的閉包
type iAdder func(int) (int, iAdder)
func adder2(base int) iAdder {
   return func(v int) (int, iAdder) {
      return base + v, adder2(base + v)
   }
}

//使用閉包實現(xiàn)斐波那契數(shù)列
func Fibonacci() func() int {
   a, b := 0, 1
   return func() int {
      a, b = b, a+b
      return a
   }
}

func main() {
   //普通閉包調(diào)用
   a := adder()
   for i := 0; i < 10; i++ {
      var s int =a(i)
      fmt.Printf("0 +...+ %d = %d\n",i, s)
   }
   //狀態(tài) 無變量的閉包 調(diào)用
   b := adder2(0)
   for i := 0; i < 10; i++ {
      var s int
      s, b = b(i)
      fmt.Printf("0 +...+ %d = %d\n",i, s)
   }

   //調(diào)用斐波那契數(shù)列生成
   fib:=Fibonacci()
   fmt.Println(fib(),fib(),fib(),fib(),fib(),fib(),fib(),fib())
}

當(dāng)前標(biāo)題:Go語言開發(fā)(六)、Go語言閉包
網(wǎng)站鏈接:http://weahome.cn/article/jhjeod.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部