概念
在C和C++中,函數是一組指令的集合,這組指令的入口地址用函數名來表示,所以,在C和C++中,函數名稱是一個地址。
但是在Go語言中,函數是一種類型,而且是第一類型(first-class)。他的地位和int string等類型是一樣的。
我們經常會聲明一個實值型別為int或者string類型的變數,現在我們可以聲明一個實值型別為某個函數的變數,這種變數叫做函數變數也就是說,函數可以被當做一個實值型別賦值給變數
例子:
func Add(a,b int)int{ return a+b}func simple01(){ //聲明一個int類型的變數 var number = 3 fmt.Println(number) //聲明一個string類型的變數 str:="aabbcc" fmt.Println(str) //現在我們聲明一個函數類型的變數 myFunc:=Add //通過函數變數調用函數(用函數指標來理解,還是很容易的) fmt.Println(myFunc(1,2))}
執行結果:
3
aabbcc
3
函數變數的用法
最基本的用法,函數變數被直接當做值進行傳遞,如:傳入函數的參數可以傳入一個函數變數
另外一種使用方法,最常用的方法,使用tyep關鍵字定義一個底層類型為函數類型的自訂類類型。函數被當做值賦值給這種變數的時候,函數的簽名必須相同(函數的參數和傳回值)
例子:
type ProcessBasename func(string)string//basename函數 移除字串的路徑部分和.尾碼 只取檔案名稱func basename(str string)string{ //去除路徑部分 slash:=strings.LastIndex(str,"/") //如果沒有找到"/" LastIndex返回-1 str=str[slash+1:] //取出.的前一部分 if dot:=strings.LastIndex(str,".");dot>0{ str = str[:dot] } return str}//這個函數使用了函數變數作為參數func GetBaseName(str string,myBasenameFunc func(string)string)string{ return myBasenameFunc(str)}//這個函數使用了type關鍵字自訂的類型(底層是一種函數類型)func GetBaseName1(str string,processBasename ProcessBasename)string{ return processBasename(str)}//函數變數被當做函數參數傳遞func simple02(){ str:="a/b/c.go" //將函數basename作為實參傳遞給GetBaseName //要注意,函數變數basename的函數簽名要和形參myBasenameFunc的函數簽名完全一致 //在這裡,函數簽名是指 函數的參數和傳回值 fmt.Println(GetBaseName(str,basename)) str1:="c.d.go" fmt.Println(GetBaseName1(str1,basename))}
執行結果:
c
c.d
總結
函數變數使用的步驟和意義
1.定義一個底層為函數類型的自訂類型 2.實現定義的函數類型 3.作為參數調用
使用函數變數,可以使得程式在調用該函數類型的地方根據使用者傳遞的實際函數來執行邏輯。使得程式更加靈活
例子:在程式中根據使用者傳遞的實際函數來實現兩個數字加還是減
type CalculateFunc func(a,b int)intfunc Add(a,b int)int{ return a+b}func Sub(a,b int)int{ return a-b}func Calculate(a,b int,calculateFunc CalculateFunc)int{ return calculateFunc(a,b)}func simple03(){ a,b:=5,3 //相加 add:=Calculate(a,b,Add) //相減 sub:=Calculate(a,b,Sub) println(add,sub)}func main(){ simple01() simple02() simple03()}
執行結果:
8 2