函数就是一段具有特定功能的代码块
go语言中常用函数声明的格式:
func 函数名(参数列表) 返回值 {
// 函数体
}
函数可以有参数,也可以没有参数,可以有返回值,也可以没有返回值;
go语言中的引用类型: slice map channel interface func();传递的是地址;
引用类型作为参数时,称为浅拷贝,形参改变,实参也跟随改变,因为传递的是地址,形参和实参都指向同一块地址;
理论上函数的返回值可以无限多个,但一般不会定义太多返回值的函数,后面会用结构体来代替多返回值;
匿名函数:
匿名函数不需要有函数名,一般都是在声明的地方直接调用;
因为没有名字,不方便在其他地方调用,调用即在函数声明的大括号后面紧跟一个小括号表示调用,中间可以有空格,但是不能有换行;
匿名函数都是声明在其他函数内部,不能定义在函数外部,因为没办法去调用它;匿名函数不调用编译报错;
函数变量:
在go语言中,函数也是一种类型,函数有多少中形式,函数变量就有多少种写法;
函数可以作为参数,也可以作为返回值;
在go语言中,函数也是一种类型,函数有多少中形式,函数变量就有多少种写法;
var a func()
var b func(int)
var c func(int) string
fmt.Println(a, b, c) // 指针类型,此时不会申请内存空间;
定义完函数变量后,可以使用匿名函数进行赋值,也可以使用已经定义好的函数进行赋值;
函数变量定义以后与普通函数调用语法相同,变量名就是普通函数声明的函数名;
package main
import "fmt"
func main() {
noArgNoReturn() // noArgNoReturn函数执行了
hasAnArgNoReturn(999) // 您输入的数字是: 999
hasArgsNoReturn(666, 777) // 您输入的数字分别是: 666 777
hasArgsHasReturn(12, 23) // 35
// 上面的函数有一个返回值,可以定义一个变量来接收
sum := hasArgsHasReturn(11, 22)
fmt.Println("返回的结果是: ", sum) // 两数相加的结果是: 33 返回的结果是: 33
res := add(2, 3)
fmt.Println("add(2, 3)计算的结果是: ", res) // add(2, 3)计算的结果是: 5
// 接收多返回值, 要么不接收,要么就用与返回值数量相等的变量来接收, 如果某个返回值不需要使用,可以用下划线_来占位
result, err := mutilReturn(1, 2)
fmt.Println(result, err) // 3 Successful!
r, _ := mutilReturn(3, 4)
fmt.Println(r) // 7
// 测试多个下划线接收
x, _, _ := testLine()
fmt.Println(x) // 测试下划线 1
// 可变参数函数
varArgs("张三", "上海", 22, "Programmer")
/*
张三的个人信息有:
0 上海
1 22
2 Programmer
*/
// 匿名函数
anonymousFunc()
// 函数变量
funcVariable()
}
func noArgNoReturn() {
// 没有参数,没有返回值的函数
fmt.Println("noArgNoReturn函数执行了")
}
func hasAnArgNoReturn(n int) {
// 有1个参数, 没有返回值
fmt.Println("您输入的数字是: ", n)
}
func hasArgsNoReturn(a, b int) {
// 有两个参数,没有返回值
fmt.Println("您输入的数字分别是: ", a, b)
}
func hasArgsHasReturn(a, b int) int {
sum := a + b
fmt.Println("两数相加的结果是: ", sum)
return sum
}
// 上面的函数可以改写成
func add(a, b int) (sum int) {
sum = a + b
return // 这里的return不用写返回的内容是什么,因为在第一行已经定义了,返回值就是sum
}
// 多返回值函数, 多返回值函数的返回值可以不接收,但是如果要接收,就需要和返回值数量相等的变量去接收
func mutilReturn(a, b int) (res int, err string) {
res = a + b
err = "Successful!"
return
}
// 测试能不能用多个下划线接收返回值
func testLine() (int, int, int) {
fmt.Println("测试下划线")
return 1, 2, 3
}
// 可变参数函数 可以将可变参数看做切片
func varArgs(name string, info ...interface{}) {
fmt.Printf("%s的个人信息有: \n", name)
for i, n := range info {
fmt.Println(i, n)
}
}
// 匿名函数
func anonymousFunc() {
// 无参匿名函数
func() {
fmt.Println("这是匿名函数")
}() // 紧跟小括号表示调用 如果不调用编译报错: func literal evaluated but not used
// 有参数的匿名函数
func(s string) {
fmt.Println("传入的参数是: ", s)
}("参数xxx") // 传入的参数是: 参数xxx
// 有参数有返回值的匿名函数
r := func(s string) (res string) {
fmt.Println("有参数有返回值的匿名函数")
return "返回值"
}("参数yyy")
fmt.Println(r)
}
// 函数变量
/*
在go语言中,函数也是一种类型,函数有多少中形式,函数变量就有多少种写法
var a func()
var b func(int)
var c func(int) string
fmt.Println(a, b, c) // <nil> <nil> <nil> 指针类型,此时不会申请内存空间
定义完函数变量后,可以使用匿名函数进行赋值,也可以使用已经定义好的函数进行赋值;
函数变量定义以后与普通函数调用语法相同,变量名就是普通函数声明的函数名;
*/
func funcVariable() {
// 函数变量
var a func()
a = func() {
fmt.Println("这是函数变量对应的函数体")
} // 注意,这里不加括号表示的是对函数变量进行赋值,调用需要加括号,或者在后面使用变量名加括号
a() // 调用函数 // 这是函数变量对应的函数体
}