日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Go 学习笔记(16)— 函数(02)[函数签名、有名函数、匿名函数、调用匿名函数、匿名函数赋值给变量、匿名函数做回调函数]

發布時間:2023/11/27 生活经验 38 豆豆

1. 函數簽名

函數類型也叫做函數簽名,可以使用 fmt.Printf("%T") 格式化參數打印函數類型。

package mainimport "fmt"func sumTwo(a []int) (ret int) {for _, v := range a {ret += v}return
}
func main() {n := []int{1, 2, 3, 4, 5}result := sumTwo(n) fmt.Println("result is ", result)	// result is  15fmt.Printf("sumTwo type is %T\n", sumTwo) // sumTwo type is func([]int) int}

兩個函數類型相同的條件是:擁有相同的形參列表和返回值列表,其中列表元素的次序、個數和類型都相同,形參名稱可以不相同。

Go 語言中,函數可是一等的(first-class)公民,函數類型也是一等的數據類型。Go 語言在語言層面支持了函數式編程。這是什么意思呢?

簡單來說,這意味著函數不但可以用于封裝代碼、分割功能、解耦邏輯,還可以化身為普通的值,在其他函數間傳遞、賦予變量、做類型判斷和轉換等等,就像切片和字典的值那樣。
而更深層次的含義就是:函數值可以由此成為能夠被隨意傳播的獨立邏輯組件(或者說功能模塊)。

書寫函數簽名的方式與函數聲明的是一致的。只是緊挨在參數列表左邊的不是函數名稱,而是關鍵字 func 。這里函數名稱和 func 互換了一下位置而已。

函數的簽名其實就是函數的參數列表和結果列表的統稱,它定義了可用來鑒別不同函數的那些特征,同時也定義了我們與函數交互的方式。

注意,各個參數和結果的名稱不能算作函數簽名的一部分,甚至對于結果聲明來說,沒有名稱都可以。

只要兩個函數的參數列表和結果列表中的元素順序及其類型是一致的,我們就可以說它們是一樣的函數,或者說是實現了同一個函數類型的函數。

嚴格來說,函數的名稱也不能算作函數簽名的一部分,它只是我們在調用函數時,需要給定的標識符而已。

package mainimport "fmt"type Printer func(contents string) (n int, err error)/*
函數printToStd的簽名與Printer的是一致的,因此前者是后者的一個實現,即使它們的名稱以及有的結果名稱是不同的。
*/
func printToStd(contents string) (bytesNum int, err error) {return fmt.Println(contents)
}func main() {var p Printerp = printToStd // 將函數賦值給一個變量p("something")
}

2. 有名函數

有名函數是指函數有具體的名稱,有名函數的函數名可以看作函數類型的常量,可以直接使用函數名調用函數,也可以直接賦值給函數類型變量,可以通過該變量來調用該函數。

package mainimport "fmt"func sum(a, b int) int {fmt.Println("I am in sum function")return a + b
}func main() {sum(3, 10)	// 直接調用result := sum(3, 4)fmt.Println("result is ", result)f := sum	// 有名函數可以直接賦值給變量ret := f(3, 10)	// 通過該變量來調用該函數fmt.Println("ret is ", ret)
}

Go 語言中函數也是類型,可以作為參數傳遞給別的函數。

package main//定義一個函數類型,兩個 int 參數,一個 int 返回值
type math func(int, int) int//定義一個函數 add,這個函數兩個 int 參數一個 int 返回值,與 math 類型相符
func add(i int, j int) int {return i + j
}//再定義一個 multiply,這個函數同樣符合 math 類型
func multiply(i, j int) int {return i * j
}//foo 函數,需要一個 math 類型的參數,用 math 類型的函數計算第 2 和第 3 個參數數字,并返回計算結果
//稍后在 main 中我們將 add 函數和 multiply 分別作為參數傳遞給它
func foo(m math, n1, n2 int) int {return m(1, 2)
}func main() {//傳遞 add 函數和兩個數字,計算相加結果n := foo(add, 1, 2)println(n)//傳遞 multply 和兩個數字,計算相乘結果n = foo(multiply, 1, 2)println(n)
}

輸出結果:

3
2

3. 匿名函數

匿名函數是指不需要定義函數名的一種函數實現方式,由一個不帶函數名的函數聲明和函數體組成。

匿名函數顧名思義就是函數沒有名稱,匿名函數可以直接賦值給變量,可以當作實參,也可以作為返回值,還可以直接被調用。

匿名函數的定義格式如下:

func(參數列表)(返回參數列表){函數體
}

匿名函數的定義就是沒有名字的普通函數定義。

3.1 在定義時調用匿名函數

匿名函數可以在聲明后調用,例如:

func main() {func(data int) {fmt.Println("hello", data)}(100)	// }后的(100),表示對匿名函數進行調用,傳遞參數為 100。
}

或者

func main() {func() {sum := 0for i := 1; i <= 100; i++ {sum += i}fmt.Println("sum is ", sum)}()
}

3.2 將匿名函數賦值給變量

匿名函數可以被賦值,例如:

// 將匿名函數體保存到f()中
f := func(data int) {fmt.Println("hello", data)
}// 使用f()調用
f(100)

3.3 匿名函數用作回調函數

下面的代碼實現對切片的遍歷操作,遍歷中訪問每個元素的操作使用匿名函數來實現,用戶傳入不同的匿名函數體可以實現對元素不同的遍歷操作,代碼如下:

package mainimport ("fmt"
)// 遍歷切片的每個元素, 通過給定函數進行元素訪問
func visit(list []int, f func(int)) {for _, v := range list {f(v)}
}func main() {// 使用匿名函數打印切片內容,// 匿名函數作為實參visit([]int{1, 2, 3, 4}, func(v int) {fmt.Println(v)})
}

3.4 匿名函數實現操作封裝

下面這段代碼將匿名函數作為 map 的鍵值,通過命令行參數動態調用匿名函數,代碼如下:

package mainimport ("flag""fmt"
)
//定義命令行參數 skill,從命令行輸入 --skill 可以將 = 后的字符串傳入 skillParam 指針變量。
var skillParam = flag.String("skill", "", "skill to perform")func main() {// 解析命令行參數,解析完成后,skillParam 指針變量將指向命令行傳入的值。flag.Parse()// 定義一個從字符串映射到 func() 的 map,然后填充這個 mapvar skill = map[string]func(){"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")}}

運行結果如下:

PS D:\code> go run main.go --skill=fly
angel fly
PS D:\code> go run main.go --skill=run
soldier run 

3.5 匿名函數其它示例

package mainimport "fmt"// 匿名函數直接賦值給變量
var sum = func(a, b int) int {return a + b
}// 匿名函數作為返回值
func swap(str string) func(int, int) int {if str == "add" {return func(a, b int) int {return a + b}}if str == "sub" {return func(a, b int) int {return a - b}}return nil}func input(f func(int, int) int, a, b int) int {return f(a, b)
}
func main() {// 匿名函數作為實參z := input(func(x, y int) int {return x + y}, 10, 20)fmt.Println("z is ", z)fmt.Println("sum(1, 3) is ", sum(1, 3))fmt.Println("swap(1, 3) is ", swap("sub")(1, 10))}

輸出:

z is  30
sum(1, 3) is  4
swap(1, 3) is  -9

匿名函數可賦值給變量,做為結構字段,或者在 channel 里傳送。

package mainfunc main() {// --- function variable ---fn := func() { println("Hello, World!") }fn()// --- function collection ---fns := [](func(x int) int){func(x int) int { return x + 1 },func(x int) int { return x + 2 },}println(fns[0](100))// --- function as field ---d := struct {fn func() string}{fn: func() string { return "Hello, World!" },}println(d.fn())// --- channel of function ---fc := make(chan func() string, 2)fc <- func() string { return "Hello, World!" }println((<-fc)())
}

輸出:

Hello, World!
101
Hello, World!
Hello, World!

總結

以上是生活随笔為你收集整理的Go 学习笔记(16)— 函数(02)[函数签名、有名函数、匿名函数、调用匿名函数、匿名函数赋值给变量、匿名函数做回调函数]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产剧情精品 | 久久九精品| 日韩欧美国产综合 | 日本熟妇毛耸耸xxxxxx | 91成人免费在线视频 | av在观看| 91最新入口| 一区视频 | 日韩午夜毛片 | 国产综合欧美 | 国产原创在线视频 | 日韩少妇毛片 | 色吧av| av片久久| 色撸撸在线视频 | 国产在线视频二区 | 亚洲欧美国产高清va在线播放 | 在线99视频 | 蜜臀av一区二区三区有限公司 | 亚欧精品在线观看 | 青青青国产视频 | 午夜精品久久久久久久99黑人 | 第四色成人网 | 国产亚洲一区二区三区不卡 | 欧美成人精品欧美一级乱黄 | 我的丝袜美腿尤物麻麻 | 日日爱99| 日韩欧美国产视频 | 欧美日韩国产一区二区 | 夜夜操天天操 | 三级特黄 | 日本少妇xxx | 久草高清视频 | 国产精品视频一二区 | 成人毛片视频免费看 | 色婷婷久久 | 在线波多野结衣 | 五月婷婷激情综合 | 狠狠操人人干 | 性做久久久久久久免费看 | 国产真人无码作爱视频免费 | 亚洲成年人免费观看 | 轮番上阵免费观看在线电影 | 国产精品av在线播放 | 特黄特黄视频 | 久久99精品久久久久婷婷 | 性欧美1819性猛交 | 男女啪啪十八 | 日本精品视频在线播放 | 男人靠女人免费视频网站 | 国产欧美日韩精品在线 | 亚洲经典三级 | 特级丰满少妇一级aaa爱毛片 | 青青草色视频 | 精品乱子伦一区二区三区 | 中文字幕va | 国产精品毛片一区二区三区 | a级片在线视频 | av免费在线网站 | av片免费在线| 国产精品51 | 98av视频| 久久乐av | 国产激情av| x88av在线 | 疯狂撞击丝袜人妻 | 欧美成人精品二区三区99精品 | 国产麻豆精品久久一二三 | 日韩一片 | 精品在线不卡 | 浪浪视频污 | 日本一区二区三区成人 | 岛国av免费在线观看 | 精品乱码一区二区三区 | 网站免费黄色 | 美女黄视频网站 | 亚洲精品成人片在线观看精品字幕 | 中文字幕欧美另类精品亚洲 | 国产sm在线| 精品欧美一区二区久久久 | 超碰最新在线 | 五号特工组之偷天换月 | 四虎网址大全 | 国产传媒av | 99热这里只有精品18 | 2019天天干天天操 | 三级av在线免费观看 | 第一章激情艳妇 | 777在线视频| 欧美第一色 | 国产激情一区二区三区视频免樱桃 | 在线97 | 一区二区成人精品 | 影音先锋男人天堂 | 精品婷婷色一区二区三区蜜桃 | 插我一区二区在线观看 | 天堂视频免费在线观看 | 国产高潮网站 | 致命魔术电影高清在线观看 |