Go语言函数的特点
特点:
-
在Go语言当中函数构成了代码执行的逻辑结构。
-
函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句
-
每一个程序都包含很多的函数,函数是基本的代码块
-
Go语言是编译型语言,所以函数编写的顺序是无关紧要的
Go语言中的三种函数类型
-
普通的带有名字的函数
-
匿名函数或者 lambda 函数
-
方法
普通函数声明(定义)
func 函数名(形式参数列表)(返回值列表){
函数体
}
特点:
-
如果有多个返回值需要书写返回值列表,如果没有返回值则可以不书写返回值列表
-
如果形参或者多个返回值类型是相同的,不需要为每一个参数声明他的类型
实参与形参:
-
实参通过值传递的方式进行传递,因此函数的形参是实参的拷贝,对形参进行修改不会影响实参,如果实参包括引用类型,如指针、slice(切片)、map、function、channel 等类型,实参可能会由于函数的间接引用被修改。
定义一个匿名函数
匿名函数的概念:
-
需要时再定义函数
匿名函数的特点:
-
没有函数名,只有函数体
-
函数可以作为一种类型被赋值给函数类型的变量
-
匿名函数可以以变量的方式传递
组成:
不带声明的:
-
函数名
-
函数声明
-
函数体
匿名函数定义格式:
func(参数列表)(返回参数列表){
函数体
}
匿名函数的调用--->匿名函数必须定义在函数内
在定义时调用匿名函数
package main
?
import (
"fmt"
)
?
func main() {
func (data int) {
fmt.Println("Hello", data)
}(100)
}
将匿名函数赋值给变量
package main
?
import (
"fmt"
)
?
func main() {
f := func(data string) {
fmt.Println("Hello", data)
}
?
f("JunkingBoy")
}
匿名函数的作用:
-
本身就是一种值,可以方便地保存在各种容器中实现回调函数和操作封装。
匿名函数用作回调函数
示例代码:
package main
?
import "fmt"
?
func visit(list []int, f func(int)) {
/*循环取出切片的value*/
for _, v := range list {
f(v)
}
}
?
func main() {
/*使用匿名函数打印切片内容*/
visit([]int{7,8,9,1,2,3}, func(i int) {
fmt.Println(i)
})
}
代码分析:
-
func visit(list []int, f func(int)) {
/*循环取出切片的value*/
for _, v := range list {
f(v)
}
}-
在这部分代码中,函数
func(int)
是一个匿名函数,由形参f
来触发。在这里这个匿名函数func(int)
仅仅只是一个容器,没有任何的具体实现 -
for
循环将取出的切片的value
放入到匿名函数中,(注意:这里不是形成形参列表,而是每取出一次v触发一次匿名函数
)
-
-
visit([]int{7,8,9,1,2,3}, func(i int) {
fmt.Println(i)
})-
在
func(i int){}
这里才开始写匿名函数的具体实现
-
这就满足了匿名函数的概念,调用时才实现
strings包下的匿名函数设计:
func TrimFunc(s string, f func(rune) bool) string {
return TrimRightFunc(TrimLeftFunc(s, f), f)
}
匿名函数实现操作封装
示例代码:
package main
import (
"flag"
"fmt"
)
var skillParam = flag.String("skill", "", "skill to perform")
func main() {
/*解析命令行参数*/
flag.Parsed()
//利用匿名函数赋值给skill变量
var skill = map[string]func(){
"fire": func() {
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}
if f, ok := skill[*skillParam]; ok {
f()
}else {
fmt.Println("skill not found")
}
}
代码分析:
-
var skillParam = flag.String("skill", "", "skill to perform")
-
定义了命令行参数
skill
,将=
后的字符串传入skillParam
指针变量
-
-
/*解析命令行参数*/
flag.Parsed()-
解析命令行参数,解析完成后,
skillParam
指针变量将指向命令行传入的值
-
-
var skill = map[string]func()
-
定义一个字符串映射到
func()
的map
。它下面的代码是填充map
-
-
var skill = map[string]func(){
"fire": func() {
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}-
初始化
map
的键值对引用,值为匿名函数
-
-
if f, ok := skill[*skillParam]; ok
-
skillParam
是一个*string
类型的指针变量,使用*skillParam
获取到命令行传过来的值,并在 map 中查找对应命令行参数指定的字符串的函数。 -
在这里要注意:
f其实的真实的值是:var f func() = skill[*skillParam]
,ok的真实值是:var ok bool
-
if
是用来进行逻辑判断的,会根据f
的执行结果来调用是执行f()
还是打印语句 -
-