深入理解 Go 語言的一等函數(shù)及其應(yīng)用
?1.什么是 Go 中的一等函數(shù)
任何一門編程語言都離不開函數(shù),無論是命令式語言 C、多范式編程語言 C++,還是面向?qū)ο缶幊陶Z言 Java、Ruby,動態(tài)語言 Python、JavaScript,函數(shù)這一語法元素都是當(dāng)仁不讓的核心。
Go 語言沒有面向?qū)ο笳Z言的語法,比如類 、繼承、對象,但 Go 語言中最重要的部分就是支持一等函數(shù)。
在 Go 語言中,函數(shù)式唯一一種基于特定輸入、實現(xiàn)特定任務(wù)并可反饋任務(wù)執(zhí)行結(jié)果的代碼塊。本質(zhì)上 Go 程序就是一組函數(shù)的集合。
什么是一等函數(shù)
一等函數(shù)允許將函數(shù)分配給變量(將函數(shù)通過變量進(jìn)行傳遞),作為參數(shù)傳遞給其他函數(shù),并從其他函數(shù)返回。
2.匿名函數(shù)
讓我們從一個簡單的例子開始,它將一個函數(shù)分配給一個變量。
在上面的程序中,我們利用 a := func()? 給變量 a 分配了一個函數(shù),這是將一個函數(shù)賦值給一個變量的語法。
然后我們分配給 a 的函數(shù)并沒有名字,這類函數(shù)就被稱為匿名函數(shù)。
調(diào)用這個函數(shù)的唯一方法就是使用變量 a?,所以在后面使用 a()? 來調(diào)用這個函數(shù),這就會打印出 Learning first class Function;
然后我們打印變量 a? 的類型,這將打印出 func()。
運行結(jié)果:
也可以調(diào)用匿名函數(shù)而不把它賦值給一個變量,讓我們來看一下下面的例子是如何做到這一點的:
在上面的程序中,在第 8 行定義了一個匿名函數(shù)。緊接著我們在第 10 行用 () 調(diào)用該函數(shù)。這個程序?qū)⑤敵?
也可以像其他函數(shù)一樣,向匿名函數(shù)傳遞參數(shù):
我們在上面的代碼中,向匿名函數(shù)中傳入一個 n string? 字符串參數(shù),然后在調(diào)用時傳入一個 "Gophers's World!" ,此時,運行程序?qū)⒌玫饺缦碌慕Y(jié)果:
3.用戶自定義的函數(shù)類型
就像我們自定義結(jié)構(gòu)體類型一樣,在 Go 語言中也支持自定義函數(shù)類型:
上面的代碼片段創(chuàng)建了一個新的函數(shù)類型 add?,它接受兩個整數(shù)參數(shù)并返回一個整數(shù),現(xiàn)在我們可以定義 add 類型的變量,如下的代碼:
上面的程序中,我們定義了一個 add? 類型的變量,并給它分配了一個簽名與 add? 類型相符的函數(shù),接著通過 sum := a(2022,10)? 調(diào)用并將結(jié)果賦給 sum,運行程序后得到如下的結(jié)果:
4.高階函數(shù)
對高階函數(shù)的定義是這個函數(shù)至少做到以下的某一項的功能:
- 以一個或者多個函數(shù)作為參數(shù)
- 返回一個函數(shù)作為其結(jié)果
將函數(shù)作為參數(shù)傳遞給其他函數(shù)
我們定義一個函數(shù) simple? 函數(shù),它接收兩個 int 參數(shù),并返回一個 int 參數(shù),然后把匿名函數(shù)傳給變量 f?,然后把 f 作為參數(shù)傳遞給 simple? 函數(shù),最終這個程序?qū)⒋蛴?nbsp;67 輸出:
從其他函數(shù)中返回函數(shù)
現(xiàn)在讓我們重寫上面的程序,從 simple 函數(shù)中返回一個函數(shù):
運行該程序,得到結(jié)果;
5.閉包
閉包是匿名函數(shù)的一種特殊情況。閉包是匿名函數(shù),它訪問定義在函數(shù)主體之外的變量。
代碼如下:
每個閉包都與它自己周圍的變量綁定。讓我們通過一個簡單的例子來理解這意味著什么。
在上面的程序中,appendStr? 函數(shù)返回一個閉包。這個閉包被綁定到變量 t? 上,變量 a? 和 b? 是閉包,被綁定到它們自己的值 t 上。
我們傳遞參數(shù) World? 給 a?,然后 a? 的值變成了 Hello World。
傳遞參數(shù) Everyone? 給 b,然后 b? 的值變成了 Hello Everyone 。
閉包通常也是支持嵌套和 defer 工作的方法。在下面的例子中,我們可以看到一個允許我們嵌套工作的函數(shù)閉包:
運行結(jié)果:
6.一等函數(shù)的實際應(yīng)用
到目前為止,我們已經(jīng)定義了什么是第一類函數(shù),我們也看到了一些精心設(shè)計的例子來學(xué)習(xí)它們是如何工作的。現(xiàn)在讓我們來寫一個具體的程序,展示第一類函數(shù)的實際用途。
我們將創(chuàng)建一個程序,根據(jù)一些標(biāo)準(zhǔn)來過濾一部分學(xué)生。讓我們一步一步地去做。
首先讓我們定義學(xué)生類型:
下一步是編寫 filter 函數(shù)。這個函數(shù)以一個學(xué)生切片和一個確定學(xué)生是否符合過濾標(biāo)準(zhǔn)的函數(shù)為參數(shù)。如下:
在上述函數(shù)中,filter? 的第二個參數(shù)是一個函數(shù),它以一個 student 為參數(shù),返回一個 bool 。這個函數(shù)確定一個特定的學(xué)生是否符合某個標(biāo)準(zhǔn)。我們在第 3 行遍歷學(xué)生切片。如果該函數(shù)返回真,則意味著該學(xué)生通過了過濾標(biāo)準(zhǔn),并被添加到切片 r 中。
現(xiàn)在來看一個完整的程序:
在主函數(shù)中,我們首先創(chuàng)建了兩個學(xué)生 s1 和 s2,并將他們添加到片斷 s 中。現(xiàn)在我們假設(shè)要找出所有成績?yōu)?B 的學(xué)生,在上述程序中,我們通過傳遞一個檢查學(xué)生是否為 B 級的函數(shù),如果是,則返回 true。 上述程序?qū)⒋蛴。?/p>
比方說,我們想找到所有來自印度的學(xué)生。這可以通過改變過濾器函數(shù)的參數(shù)來輕松實現(xiàn)。如下:
讓我們再寫一個程序來結(jié)束本文。這個程序?qū)σ粋€切片的每個元素進(jìn)行同樣的操作,并返回結(jié)果。
例如,如果我們想將一個切片中的所有整數(shù)乘以 5,并返回輸出結(jié)果,可以用第一類函數(shù)輕松完成。
這類對集合中每個元素進(jìn)行操作的函數(shù)被稱為 map 函數(shù)。如下這個程序
運行結(jié)果:
7.總結(jié)
在本文中,介紹了什么是一等函數(shù)的概念和功能,匿名函數(shù)、用戶自定義函數(shù)類型、高階函數(shù)和閉包,最后給出了一等函數(shù)的實際應(yīng)用例子,希望這篇文章對你有所幫助!