概念
在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)int
func 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