從go語言閉包談函數式程式設計
這篇文章從下面幾個面向學習函數式程式設計:
1、數學公式和函數式程式設計有什麼關係
#舉個簡單例子吧,數學中有一個概念叫做映射(y=f(x)),說的通俗一點就是函數啦。而最熟悉的應該就是二次函數(拋物線y=a*x*x b*x c)
現在coding實現求拋物線上某一點的值,我們知道a,b,c是參數,x是自變量,y是因變量,如果是以前,我也許會這麼實現(為了紀念我許久未寫的c ,還是用c 來寫一下)
double getParabola(double a,double b,double c,double x) { return a*x*x+b*x+c; }
問題一、給定拋物線,求x =2,x=3,x=4時的值,就是下面的做法了
resultA = getParabola(a,b,c,2) resultB = getParabola(a,b,c,2) resultC = getParabola(a,b,c,2)
這在程式中,是很正常的做法。但是,如果從數學的角度來看,有沒有辦法變得符合數學公式思考呢?以下是我的另一個實作(這裡用go來實作哈,因為c 我知道怎麼寫),
func getParabola(aa,bb,cc float32){ var a = aa var b = bb var c = cc a := func(x float32) { return a*x*x+b*x+c } return a }
然後,同樣是對於問題一,解決方案如下
parabola := getParabola(a,b,c) resultA := parabola(2) resultB := parabola(3) resultC := parabola(4)
是不是跟求函數值一樣?所以,數學關係在函數式程式設計中得到了很好的體現。
2、函數式程式設計有什麼特點,go支援了哪些概念
函數式程式有三大特性
1.變數的不可變性: 變數一經賦值不可改變。如果需要改變,則必須複製出去,然後修改。 go中,string變數一經賦值,不可以像c 那樣,c[2]='a'這樣的修改,而是要明確轉換為[]byte,然後再進行修改。但是已經是另外一塊記憶體了。
2、函數式一等公民: 函數也是變量,可以作為參數,返回值等在程式中傳遞。這個特性,c 和go應該都是支援的。
3、尾遞歸:遞歸的概念在斐波那契數列的時候,就學習過了。如果遞歸很深的話,堆疊可能會爆掉,並導致效能大幅下降。而尾遞歸優化技術,編譯器如果支援的話,可以在每次遞歸時重用stack(尾遞歸表示遞歸調用發生在最後一步,這個時候,之前的結果都作為參數傳遞給最後一步的調用,所以之前的狀態就沒有任何作用了,所以可以重複使用stack)。
函數式程式設計常用技術
1、map&reduce&filter
map用於對每一個輸入,呼叫同一個函數,產生一個輸出,例如c 中的for_each,hadoop裡面的map,python的map等。
reduce用於對每一個輸入,加上上一個輸出,得到下一個輸出,例如python和hadoop中的reduce,
filter用於做過濾,例如c 的count_if等。
2、遞迴
3、pipeline
把函數實例放到一個陣列或是列表中,然後把資料傳給這個action list,輸入順序地被各個函數所操作(意思是每一個函數的輸出,作為另外一個函數的輸入,資料是流動的,計算是固定的,類似storm的概念),最終得到我們想要的結果。
4、其他(有待進一步學習)
3、函數式程式設計與運行效率
函數式程式設計最重要的一個概念就是函數式一等公民,函數跟變數是一樣的。可以作為參數,傳回值等。不贊成使用賦值語句,所以比較多的使用遞歸,所以函數式程式設計效率一定會比較低。
最近我用的比較多的是閉包,閉包的概念就是一個環境(一個或多個變數)加上一個函數,每一次對閉包表達式求值,都得到一個隔離的結果,這跟普通函數是不一樣的,普通函數就是一段可執行的程式碼,只要入口確定了,呼叫的位置也就確定了。舉個例子,上面拋物線的例子,呼叫
a:=getParabola(0.2,0.1,0.3) b:=getParabola(0.1,0.1,0.4)
得到的是兩條拋物線。之所以我覺得效率會降低,是因為閉包本身就是一個求值賦值的過程,牽涉到變數的創建銷毀。當然,我沒有實際去測試性能。如果後續發行server效率降低,也許這是一個需要考慮的地方。
更多go語言知識請關注PHP中文網go語言教學專欄。
以上是從go語言閉包談函數式程式設計的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

在Go中,可以使用gorilla/websocket包發送WebSocket訊息。具體步驟:建立WebSocket連線。傳送文字訊息:呼叫WriteMessage(websocket.TextMessage,[]byte("訊息"))。發送二進位訊息:呼叫WriteMessage(websocket.BinaryMessage,[]byte{1,2,3})。

在Go中,函數生命週期包括定義、載入、連結、初始化、呼叫和返回;變數作用域分為函數級和區塊級,函數內的變數在內部可見,而區塊內的變數僅在區塊內可見。

在Go中,可以使用正規表示式比對時間戳記:編譯正規表示式字串,例如用於匹配ISO8601時間戳記的表達式:^\d{4}-\d{2}-\d{2}T \d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ 。使用regexp.MatchString函數檢查字串是否與正規表示式相符。

記憶體洩漏會導致Go程式記憶體不斷增加,可通過:關閉不再使用的資源,如檔案、網路連線和資料庫連線。使用弱引用防止記憶體洩漏,當物件不再被強引用時將其作為垃圾回收目標。利用go協程,協程棧記憶體會在退出時自動釋放,避免記憶體洩漏。

Go和Go語言是不同的實體,具有不同的特性。 Go(又稱Golang)以其並發性、編譯速度快、記憶體管理和跨平台優點而聞名。 Go語言的缺點包括生態系統不如其他語言豐富、文法更嚴格、缺乏動態類型。

使用IDE檢視Go函數文件:將遊標停留在函數名稱上。按下熱鍵(GoLand:Ctrl+Q;VSCode:安裝GoExtensionPack後,F1並選擇"Go:ShowDocumentation")。

在Golang中,錯誤包裝器允許你在原始錯誤上追加上下文訊息,從而創建新錯誤。這可用於統一不同程式庫或元件拋出的錯誤類型,簡化偵錯和錯誤處理。步驟如下:使用errors.Wrap函數將原有錯誤包裝成新錯誤。新錯誤包含原始錯誤的上下文資訊。使用fmt.Printf輸出包裝後的錯誤,提供更多上下文和可操作性。在處理不同類型的錯誤時,使用errors.Wrap函數統一錯誤類型。

對並發函數進行單元測試至關重要,因為這有助於確保其在並發環境中的正確行為。測試並發函數時必須考慮互斥、同步和隔離等基本原理。可以透過模擬、測試競爭條件和驗證結果等方法對並發函數進行單元測試。
