函数
声明函数
普通函数的声明形式
普通函数需要先声明才能调用,一个函数的声明包括参数和函数名等,编译器通过声明才能了解函数应该怎样在调用代码和函数体之间传递参数和返回参数
声明方式
- 函数名:有字母、数字、下划线组成,其中函数名的第一个字母不能为数字,在同一个包内,函数名称不能重复
- 参数列表 :一个参数由参数变量和参数类型组成,例如
func foo(a int, b string)
,其中参数列表中的变量作为函数的局部变量而存在 - 返回参数列表:可以是返回值类型列表,也可以是类似参数列表中变量名和类型名的组合,函数在声明有返回值时,必须在函数体中使用
return
语句提供返回值列表 - 函数体 :能够被重复调用的代码片段
func 函数名(参数列表) (返回参数列表) {
函数体
}
参数类型的简写
在参数列表中,如果有多个参数变量,则以逗号分隔,如果相邻变量是同类型,则可以将类型省略
- 单一返回值
- 多个返回值
- 命名返回值
func add(a, b int) int {
return a + b
}
func calculate(a, b int) (int, int) {
sum := a + b
product := a * b
return sum, product
}
返回多个值时,需要用一组变量来接收它们
sum, product := calculate(3, 5)
fmt.Println("Sum:", sum, "Product:", product)
这里使用了go的 明明返回值
特性,它的作用是为返回值起一个名字(在这里是 result
),并在函数内部直接操作这个命名返回值,最终通过 return
隐式地返回它
func add(a, b int) (result int) {
result = a + b
return // 隐式返回 result
}
函数的返回值
go语言支持多返回值,多返回值能方便的获得函数执行后多个返回参数,go语言经常使用多返回值中的最后一个返回参数返回函数执行中可能发生的错误
connectToNetwork
返回两个参数,conn
表示连接对象,err
返回错误
conn, err = connectToNetwork()
同一种类型返回值
如果返回值是同一种类型,则用括号将多个返回值类型括起来,用逗号分隔每个返回值的类型
使用 return
语句返回时,值列表的顺序需要与函数声明的返回值类型一致
package main
import "fmt"
func typedTwoValues() (int, int) {
return 1, 2
}
func main() {
a, b := typedTwoValues() // 调用函数并解构返回值
fmt.Println(a, b) // 输出:1 2
}
带有变量名的返回值
go语言支持对返回值进行命名,这样返回值就和参数一样拥有参数变量名和类型
命名的返回值变量的默认值为类型的默认值,即数值 为0,字符串为空字符串,布尔为 false
、指针为 nil
等
package main
import "fmt"
func namedRetValues() (a, b int) { // a和b是返回值变量名
a = 1
b = 2
return
}
func main() {
x, y := namedRetValues() // x和y是接收返回值的变量名
fmt.Println(x, y) // 输出:1 2
}
同一种类型返回值和命名返回值两种形式只能二选一,混用时将会发生编译错误
调用函数
函数在定义后,可以通过调用的方式,让当前的代码跳转到被调用的函数中进行执行,调用前的函数局部变量都会被保存起来不会丢失,被调用的函数结束后,恢复到被调用函数的下一行继续执行代码,之前的局部变量也能继续访问
函数内的局部变量只能在函数体中使用,函数调用结束后,这些局部变量都会被释放并且失效
函数调用格式
- 函数名 :需要调用的函数名
- 参数列表 :参数变量以逗号分隔,尾部无须以分号结尾
- 返回值变量列表 :多个返回值使用逗号分隔
返回值变量列表 = 函数名(参数列表)
不包含参数的调用
package main
import "fmt"
func namedRetValues() (a, b int) {
a = 1
b = 2
return
}
func main() {
x, y := namedRetValues() // 调用函数 namedRetValues,解构返回值,没有参数
fmt.Println(x, y) // 调用 fmt.Println,输出 x 和 y
}
包含参数的调用
单个参数
package main
import "fmt"
// 定义一个带单个参数的函数
func greet(name string) string {
return fmt.Sprintf("Hello, %s!", name)
}
func main() {
// 调用函数时传递一个参数
message := greet("Alice")
fmt.Println(message) // 输出:Hello, Alice!
}
多个参数
package main
import "fmt"
// 定义一个带多个参数的函数
func add(a int, b int) int {
return a + b
}
func main() {
// 调用带参数的函数
result := add(3, 5)
fmt.Println("Result:", result) // 输出:Result: 8
}
可变参数的函数调用
go支持可变参数,通过 ...
表示,这种函数可以接收任意数量的参数
package main
import "fmt"
// 定义一个可变参数的函数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
func main() {
// 调用函数,传递任意数量的参数
result := sum(1, 2, 3, 4, 5)
fmt.Println("Sum:", result) // 输出:Sum: 15
}
函数变量 - 把函数作为值保存到变量中
在go语言中,函数也是一种类型,可以和其他类型一样被保存在变量中,下面的代码定义了一个函数变量 f
,并将一个函数名 fire()
赋值给函数变量 f
,这样调用函数变量 f
时,实际调用的就是 fire()
函数
package main
import "fmt"
func fire() {
fmt.Println("我尼玛,爱嫂子啊?")
}
func main() {
var f func()
f = fire
f()
}
匿名函数 - 没有函数名字的函数
go语言支持匿名函数,即在需要使用函数时,再定义函数,匿名函数没有函数名,只有函数体,函数可以被作为一种类型被赋值给函数类型的变量,匿名函数也往往以变量方式被传递
匿名函数经常被用于实现回调函数、闭包等
定义匿名函数
匿名函数的定义格式
func(参数列表) (返回参数列表) {
函数体
}
匿名函数的定义就是没有名字的普通函数定义
在定义时调用匿名函数
func(data int) {
fmt.Println("hello", data)
}(100) // (100)表示对匿名函数进行调用,传递参数为100
匿名函数需要放在某个函数(如 main
或自定义函数)中才能运行
- main
- 自定义函数
package main
import "fmt"
func main() {
func(data int) {
fmt.Println("hello", data)
}(100)
}
package main
import "fmt"
func anotherFunction() {
func(data int) {
fmt.Println("hello", data)
}(200)
}
func main() {
anotherFunction() // 输出: hello 200
}
将匿名函数赋值给变量
匿名函数体可以被赋值
package main
import "fmt"
func main() {
// 将匿名函数赋值给变量 f
f := func(data int) {
fmt.Println("hello", data)
}
// 使用 f 调用匿名函数
f(100) // 输出: hello 100
}