Day05(函数)
函数
函数定义和调用
在 Go 语言中,函数的定义方式如下:
1
2
3
4
func functionName(parameter1 type1, parameter2 type2) returnType {
// 函数体
return value
}
例如,一个简单的加法函数可以这样定义和调用:
1
2
3
4
5
6
7
8
9
10
11
12
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
result := add(3, 4)
fmt.Println(result) // 输出: 7
}
多个返回值
Go 语言支持函数返回多个值,这在处理错误时特别有用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func divide(dividend int, divisor int) (int, error) {
if divisor == 0 {
return 0, fmt.Errorf("division by zero")
}
return dividend / divisor, nil
}
func main() {
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result)
}
}
命名返回值
函数的返回值可以被命名,这使得函数体中的代码更为清晰:
1
2
3
4
5
6
7
8
9
10
11
func addAndMultiply(x, y int) (sum int, product int) {
sum = x + y
product = x * y
return
}
func main() {
sum, product := addAndMultiply(3, 4)
fmt.Println("Sum:", sum) // 输出: Sum: 7
fmt.Println("Product:", product) // 输出: Product: 12
}
匿名函数和闭包
Go 语言支持匿名函数和闭包,可以在函数内部定义一个匿名函数并调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
// 匿名函数
result := func(x, y int) int {
return x + y
}(3, 4)
fmt.Println(result) // 输出: 7
// 闭包
add := func(x int) int {
return x + 10
}
fmt.Println(add(5)) // 输出: 15
}
方法
在 Go 语言中,函数可以附属于一个类型,这样的函数称为方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
type Rectangle struct {
width, height int
}
// 方法
func (r Rectangle) Area() int {
return r.width * r.height
}
func main() {
rect := Rectangle{width: 10, height: 5}
fmt.Println("Area:", rect.Area()) // 输出: Area: 50
}
递归函数
函数可以调用自身,这就是递归:
1
2
3
4
5
6
7
8
9
10
func factorial(n int) int {
if n == 0 {
return 1
}
return n * factorial(n-1)
}
func main() {
fmt.Println(factorial(5)) // 输出: 120
}
defer 语句
defer
语句用于延迟执行某个函数直到当前函数返回,这在资源清理等场景中很有用:
1
2
3
4
5
6
func main() {
fmt.Println("Start")
defer fmt.Println("Deferred")
fmt.Println("End")
// 输出顺序: Start, End, Deferred
}
函数传参方式
值传递
值传递是指在函数调用时,将实际参数的副本传递给函数。这样,函数内对参数的修改不会影响到函数外的变量。
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"
func modifyValue(val int) {
val = 10
}
func main() {
a := 5
modifyValue(a)
fmt.Println(a) // 输出: 5
}
modifyValue
函数修改了参数val
的值,但这并不影响函数外的变量a
。
引用传递(通过指针实现)
引用传递的效果是通过传递指针来实现的。传递指针允许函数修改外部变量的值。
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"
func modifyPointer(val *int) {
*val = 10
}
func main() {
a := 5
modifyPointer(&a)
fmt.Println(a) // 输出: 10
}
modifyPointer
函数接收一个指向int
类型的指针,并修改该指针指向的值。由于传递的是指针,函数内的修改会影响到外部变量a
。
-
示例对比(为了更清楚地理解值传递和通过指针实现的引用传递)
-
值传递示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import "fmt"
type Point struct {
x, y int
}
func modifyPointVal(p Point) {
p.x = 10
p.y = 10
}
func main() {
p := Point{1, 2}
modifyPointVal(p)
fmt.Println(p) // 输出: {1, 2}
}
modifyPointVal
函数接收的是Point
结构体的副本,因此对p
的修改不会影响函数外的变量p
。
- 引用传递(通过指针实现)示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import "fmt"
type Point struct {
x, y int
}
func modifyPointPtr(p *Point) {
p.x = 10
p.y = 10
}
func main() {
p := Point{1, 2}
modifyPointPtr(&p)
fmt.Println(p) // 输出: {10, 10}
}
modifyPointPtr
函数接收的是指向Point
结构体的指针,因此对p
的修改会影响函数外的变量p
。
总结
- 值传递:将参数的副本传递给函数。函数内部对参数的修改不会影响到外部变量。
- 引用传递(通过指针实现):传递参数的指针,使得函数能够修改外部变量的值。
特殊用法
可变参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import "fmt"
// 定义一个可变参数函数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
func main() {
fmt.Println(sum(1, 2, 3)) // 输出: 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 输出: 15
}
方法(附属于类型的函数)
方法是附属于某个类型的函数,方法可以有接收者,可以是值类型或指针类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import "fmt"
type Rectangle struct {
width, height int
}
// 值接收者方法
func (r Rectangle) Area() int {
return r.width * r.height
}
// 指针接收者方法
func (r *Rectangle) Scale(factor int) {
r.width *= factor
r.height *= factor
}
func main() {
rect := Rectangle{width: 10, height: 5}
fmt.Println("Area:", rect.Area()) // 输出: Area: 50
rect.Scale(2)
fmt.Println("Scaled Area:", rect.Area()) // 输出: Scaled Area: 200
}
高阶函数
高阶函数是指接受函数作为参数或返回函数的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
import "fmt"
// 高阶函数,返回一个函数
func makeAdder(x int) func(int) int {
return func(y int) int {
return x + y
}
}
func main() {
add5 := makeAdder(5)
fmt.Println(add5(3)) // 输出: 8
fmt.Println(add5(10)) // 输出: 15
}
This post is licensed under
CC BY 4.0
by the author.