1. 函数定义 — 基本语法
Go 函数用 func 关键字定义,最简单的形式:无参数、无返回值:
package main
import "fmt"
// greet 函数:无参数、无返回值
func greet() {
fmt.Println("Hello from a function!")
}
func main() {
fmt.Println("This runs before the function call")
greet()
fmt.Println("This runs after the function call")
}
执行结果:
This runs before the function call
Hello from a function!
This runs after the function call
要点:
-
func greet()—func关键字 + 函数名 + 参数列表 + 返回类型 - 无参数时写空括号
(),无返回值时省略返回类型 - 函数调用:
greet()— 直接用函数名加括号 - 执行顺序:main 中代码按顺序执行,
greet()在两行 Println 之间被调用 - 函数定义必须在
main()之前(或同级),Go 不支持函数嵌套定义(不支持在函数内定义函数,但支持匿名函数)
2. 函数参数 — 传入数据
函数通过参数接收外部数据,参数在函数内部作为局部变量使用:
package main
import "fmt"
// 单个参数
func greetPerson(name string) {
fmt.Println("Hello, " + name + "!")
}
// 多个参数(各自指定类型)
func add(a int, b int) {
result := a + b
fmt.Println("The sum is:", result)
}
func main() {
greetPerson("Alice")
greetPerson("Bob")
add(5, 3)
add(10, 7)
}
执行结果:
Hello, Alice!
Hello, Bob!
The sum is: 8
The sum is: 17
要点:
-
func greetPerson(name string)— 一个 string 参数 -
func add(a int, b int)— 两个 int 参数,各自声明类型 - 连续同类型参数可省略前面的类型声明:
func add(a, b int)等价于func add(a int, b int) - 参数是值传递:函数收到的是值的拷贝,修改参数不影响原值
- 字符串拼接:
"Hello, " + name + "!"— Go 用+拼接字符串
3. 返回值 — 函数输出数据
函数通过 return 返回结果给调用者,Go 支持多返回值:
package main
import "fmt"
// 单个返回值
func double(x int) int {
return x * 2
}
// 单个返回值(string)
func getGreeting(name string) string {
return "Hello, " + name + "!"
}
// 多返回值 — 返回结果 + 成功标志
func divide(a, b float64) (float64, bool) {
if b == 0 {
return 0.0, false
}
return a / b, true
}
func main() {
result := double(5)
fmt.Println("Double of 5 is:", result)
greeting := getGreeting("World")
fmt.Println(greeting)
quotient, success := divide(10.0, 2.0)
fmt.Println("10.0 / 2.0 =", quotient, "Success:", success)
quotient2, success2 := divide(10.0, 0.0)
fmt.Println("10.0 / 0.0 =", quotient2, "Success:", success2)
}
执行结果:
Double of 5 is: 10
Hello, World!
10.0 / 2.0 = 5 Success: true
10.0 / 0.0 = 0 Success: false
要点:
- 返回类型写在参数列表后面:
func double(x int) int— 最后的int是返回类型 - 多返回值用括号包裹:
(float64, bool)— 返回两个值 -
return a / b, true— 同时返回两个值,用逗号分隔 - 调用方用多重赋值接收:
quotient, success := divide(10.0, 2.0) - 多返回值是 Go 的核心特性,最常见的用法是
(result, error)模式:func readFile(path string) (string, error) { ... } content, err := readFile("data.txt") if err != nil { // 处理错误 } - 如果只想接收其中一个返回值,用
_忽略:quotient, _ := divide(10.0, 2.0)
4. 命名返回值 — 裸返回(naked return)
返回值可以命名,命名后函数内直接赋值,return 不需要指定值:
package main
import "fmt"
// 命名返回值:area 和 perimeter
func calculateArea(width, height float64) (area, perimeter float64) {
area = width * height
perimeter = 2 * (width + height)
return // naked return — 自动返回 area 和 perimeter
}
// 命名返回值:first 和 second
func swapStrings(a, b string) (first, second string) {
first = b
second = a
return // naked return — 自动返回 first 和 second
}
func main() {
area, perimeter := calculateArea(5.0, 3.0)
fmt.Println("Area:", area, "Perimeter:", perimeter)
first, second := swapStrings("hello", "world")
fmt.Println("First:", first, "Second:", second)
}
执行结果:
Area: 15 Perimeter: 16
First: world Second: hello
要点:
-
(area, perimeter float64)— 返回值命名,在函数内作为局部变量直接使用 - 命名后
area = width * height— 直接赋值,不需要return width * height -
return— 裸返回,自动返回命名变量的当前值(不需要写return area, perimeter) - 调用方仍用多重赋值接收:
area, perimeter := calculateArea(5.0, 3.0) - 裸返回适合短函数;长函数推荐显式
return值,避免遗忘赋值导致返回零值 - 命名返回值的好处:代码自文档化,
calculateArea(width, height float64) (area, perimeter float64)直接告诉读者返回的是什么 - 命名返回值的另一个用途:在 defer 中修改返回值(见 panic/recover 知识点中的
result = 0)
5. 函数类型 — 函数作为变量和参数
函数在 Go 中是一等公民(first-class citizen),可以赋值给变量、作为参数传递:
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func multiply(a, b int) int {
return a * b
}
// operation 参数是一个函数类型
func operate(a, b int, operation func(int, int) int) int {
return operation(a, b)
}
func main() {
// 函数赋值给变量
var mathFunc func(int, int) int = add
result1 := mathFunc(5, 3)
fmt.Println("mathFunc(5, 3) with add:", result1)
// 变量可以换绑另一个函数
mathFunc = multiply
result2 := mathFunc(5, 3)
fmt.Println("mathFunc(5, 3) with multiply:", result2)
// 函数作为参数传递
result3 := operate(10, 4, add)
fmt.Println("operate(10, 4, add):", result3)
result4 := operate(10, 4, multiply)
fmt.Println("operate(10, 4, multiply):", result4)
}
执行结果:
mathFunc(5, 3) with add: 8
mathFunc(5, 3) with multiply: 15
operate(10, 4, add): 14
operate(10, 4, multiply): 40
要点:
- 函数类型签名:
func(int, int) int— 描述"接收两个 int、返回一个 int"的函数 -
var mathFunc func(int, int) int = add— 将add函数赋值给mathFunc变量 - 调用
mathFunc(5, 3)和直接调用add(5, 3)效果相同(输出 8) -
mathFunc = multiply— 变量可以重新绑定为另一个函数,调用后输出 15(5*3) -
operate(a, b int, operation func(int, int) int)— 函数作为参数!-
operation参数的类型是func(int, int) int,传入add或multiply -
operate内部调用operation(a, b),根据传入的函数执行不同运算
-
- 函数是一等公民:可以赋值给变量、作为参数传递、作为返回值(闭包就是返回函数)
- 这使得 Go 支持策略模式:同一个
operate函数,通过传入不同运算函数实现不同行为 - 实际场景:排序时传入比较函数、HTTP 路由传入处理函数等
知识点总结
| 知识点 | 关键概念 |
|---|---|
| 函数定义 |
func name() { ... },无参数无返回值的基本形式 |
| 函数参数 | 值传递,连续同类型可省略前面类型声明 a, b int
|
| 返回值 | 单返回值、多返回值 (float64, bool),Go 核心模式 (result, error)
|
| 命名返回值 |
(area, perimeter float64),裸 return,defer 中可修改返回值 |
| 函数类型 | 函数是一等公民,可赋值给变量、作为参数、作为返回值 |