匿名函數沒有函數名只有函數體,在須要函數時再定義函數。函數能夠看成變量賦值傳遞,與回調函數類似。Go語言隨時支持在代碼中定義匿名函數。html
以下爲聲明一個匿名函數,在定義時直接聲明:函數
func main() { log.Println("this is main func") func(name string) { log.Println("hello", name) }("Wzy_CC") } // out: // this is main func // hello Wzy_CC
也能夠將匿名函數賦值給變量:post
f := func(name string) { log.Println("hello", name) } f("Wzy_CC") // 調用匿名函數
匿名函數是否是真的沒有名字,以下實例,調用並打印匿名函數的名字:this
package main import ( "log" "runtime" ) func printMyName() string { pc, _, _, _ := runtime.Caller(1) // 返回函數指針 return runtime.FuncForPC(pc).Name() } func main() { var f func(string) f = func(name string) { log.Println("hello", name) log.Printf("f first assignment %s\n", printMyName()) } f("Wzy") f = func(name string) { log.Println("hello2", name) log.Printf("f second assignment %s\n", printMyName()) } f("Wzy") }
輸出結果以下:.net
2020/07/22 16:50:36 hello Wzy 2020/07/22 16:50:36 f first assignment main.main.func1 2020/07/22 16:50:36 hello2 Wzy 2020/07/22 16:50:36 f second assignment main.main.func2
看起來匿名函數彷佛仍是存在函數名的,自動編號func1~N命令行
用做回調函數:設計
下面的代碼實現對切片的遍歷操做,遍歷中訪問每一個元素的操做使用匿名函數來實現,用戶傳入不一樣的匿名函數體能夠實現對元素不一樣的遍歷操做,代碼以下:3d
package main import ( "log" ) // 遍歷切片的每一個元素, 經過給定函數進行元素訪問 func visit(list []int, f func(int)) { // 使用 visit() 函數將整個遍歷過程進行封裝 for _, v := range list { f(v) } } func main() { // 使用匿名函數打印切片內容 visit([]int{1, 2, 3, 4}, func(v int) { // 當要獲取遍歷期間的切片值時,只須要給 visit() 傳入一個回調參數便可 log.Println(v) }) }
匿名函數做爲回調函數的設計在Go語言的系統包中也比較常見,strings 包中就有相似的設計,代碼以下:指針
func TrimFunc(s string, f func(rune) bool) string { return TrimRightFunc(TrimLeftFunc(s, f), f) }
使用匿名函數進行封裝操做:code
下面這段代碼將匿名函數做爲 map 的鍵值,經過命令行參數動態調用匿名函數,代碼以下:
package main import ( "flag" // flag庫用於處理命令行參數 "fmt" ) // 定義命令行參數skill,從命令行輸入--skill能夠將=後的字符串傳入skillParam指針變量 var skillParam = flag.String("skill", "", "skill to perform") func main() { flag.Parse() // 解析命令行參數,解析完成後,skillParam指針變量將指向命令行傳入的值 var skill = map[string]func(){ // 定義一個從字符串映射到func()的map,而後填充這個map "fire": func() { // 初始化map的鍵值對,值爲匿名函數 fmt.Println("chicken fire") }, "run": func() { fmt.Println("soldier run") }, "fly": func() { fmt.Println("angel fly") }, } // skillParam是一個*string類型的指針變量,使用*skillParam獲取到命令行傳過來的值,並在map中查找對應命令行參數指定的字符串的函數 if f, ok := skill[*skillParam]; ok { f() } else { fmt.Println("skill not found") // 若是在map定義中存在這個參數就調用,不然打印「技能沒有找到」 } }
運行代碼,結果以下:
PS C:\Users\W10\Desktop\本地工程\leetcode\test2> go run main.go --skill=fly angel fly PS C:\Users\W10\Desktop\本地工程\leetcode\test2> go run main.go --skill=run soldier run