1. 函数的定义
在 Go 语言中,函数是最基本的代码组织单元。通过函数可将一段代码进行封装,使其具备独立性。Go 语言的函数定义格式如下:
func 函数名(参数列表) (返回值列表) {
函数体
}
1.1 函数名
函数名是由字母、数字和下划线组成的标识符。函数名只有被定义在包级别才是可见的(即首字母大写)。
1.2 参数列表
参数是指传递给函数的数据。Go 语言支持多种类型的参数传递方式:
1.2.1 值参数
值参数是指在函数调用过程中,传递的是实际参数的拷贝。
func add(x int, y int) int {
return x + y
}
上面的代码中,add 函数接受两个 int 类型的参数,返回它们的和。这两个参数是值参数,因为函数调用过程中传递的是它们的拷贝。
1.2.2 指针参数
指针参数是指在函数调用过程中,传递的是实际参数的地址。
func swap(x *int, y *int) {
temp := *x
*x = *y
*y = temp
}
上面的代码中,swap 函数接受两个 int 类型的指针作为参数,将它们所指的值交换。这两个参数是指针参数,因为函数调用过程中传递的是它们的地址。
1.2.3 变长参数
变长参数是指可以传递任意数量的参数。
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
上面的代码中,sum 函数接受任意数量的 int 类型参数,返回它们的和。这个函数的参数列表中的 "..." 表示变长参数。
1.3 返回值列表
返回值是指函数执行过程中返回给调用者的数据。Go 语言支持多个返回值,也可以不返回任何值。
func divide(dividend, divisor float64) (float64, error) {
if divisor == 0.0 {
return 0.0, fmt.Errorf("division by zero")
}
return dividend / divisor, nil
}
上面的代码中,divide 函数接受两个 float64 类型参数,返回它们的商和一个错误(如果除数为 0,则返回 "division by zero" 错误)。这个函数的返回值列表使用了括号包裹,因为有多个返回值。
2. 函数的调用
函数定义好了之后,就可以通过函数名来调用它,并传递相应的参数。调用函数的格式如下:
result := 函数名(参数列表)
例如,对于上面的 add 函数,可以这样调用它:
result := add(2, 3)
这将返回 5,将其保存到 result 变量中。
3. 匿名函数
匿名函数是指没有函数名的函数。它们可以直接在源代码中定义和调用,不需要像普通函数那样进行定义和声明。
func main() {
add := func(x, y int) int {
return x + y
}
result := add(2, 3)
fmt.Println(result)
}
上面的代码中,定义了一个匿名函数,将其赋值给名为 add 的变量。这个匿名函数接受两个 int 类型的参数,返回它们的和。然后调用这个变量(也就是匿名函数)并传递两个参数来计算它们的和。最后将结果输出到终端。
4. 闭包
闭包是指一个函数内部有一个或多个内部函数,这些内部函数可以访问外部函数的局部变量,并把它们保存下来。
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
c1 := counter()
fmt.Println(c1()) // 输出 1
fmt.Println(c1()) // 输出 2
fmt.Println(c1()) // 输出 3
c2 := counter()
fmt.Println(c2()) // 输出 1
fmt.Println(c2()) // 输出 2
}
上面的代码中,定义了一个 counter 函数,返回一个匿名函数。这个匿名函数会在每次调用时返回一个自增的数值。在 main 函数中,我们分别调用了两次 counter 函数,并分别将它们赋值给 c1 和 c2 两个变量。然后在通过这两个变量调用它们所保存的匿名函数,观察输出结果。
这个例子中,每次调用 counter 函数时都会创建一个新的本地变量 count。然后又创建了一个匿名函数,它访问了这个本地变量,并把它们保存下来。在每次调用这个匿名函数时,都会将这个变量的值加一,并返回它。
5. defer 语句
在 Go 语言中,可以使用 defer 语句注册一个函数,这个函数会在当前函数返回之前执行。
func cleanup() {
fmt.Println("Cleaning up...")
}
func doSomething() {
defer cleanup()
fmt.Println("Doing something...")
}
func main() {
doSomething()
}
上面的代码中,定义了一个 cleanup 函数和一个 doSomething 函数。在 doSomething 函数内部使用了 defer 语句,将 cleanup 函数注册了一次。这意味着在 doSomething 函数返回前,cleanup 函数会被执行。
6. 总结
在 Go 语言中,函数是最基本的代码组织单元。它们可以通过参数、返回值和闭包实现多种功能。在平时的编码中,应该注意代码的可读性和可维护性,避免出现过于复杂的函数。