函数基础 #
一、函数定义 #
1.1 基本语法 #
go
func 函数名(参数列表) 返回值类型 {
// 函数体
}
1.2 示例 #
go
func add(a, b int) int {
return a + b
}
func greet(name string) {
fmt.Println("Hello, " + name)
}
1.3 无参数无返回值 #
go
func sayHello() {
fmt.Println("Hello!")
}
二、参数 #
2.1 参数类型 #
go
func add(a int, b int) int {
return a + b
}
// 相邻同类型参数可简写
func add(a, b int) int {
return a + b
}
// 不同类型参数
func printInfo(name string, age int) {
fmt.Printf("%s is %d years old\n", name, age)
}
2.2 值传递 #
Go默认值传递,函数内修改不影响原值:
go
func double(n int) {
n = n * 2
}
func main() {
x := 10
double(x)
fmt.Println(x) // 10,未改变
}
2.3 指针传递 #
使用指针可以修改原值:
go
func double(n *int) {
*n = *n * 2
}
func main() {
x := 10
double(&x)
fmt.Println(x) // 20
}
2.4 可变参数 #
使用...表示可变参数:
go
func sum(numbers ...int) int {
total := 0
for _, n := range numbers {
total += n
}
return total
}
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 15
可变参数本质是切片:
go
func printNumbers(numbers ...int) {
fmt.Printf("%T\n", numbers) // []int
}
传递切片给可变参数:
go
nums := []int{1, 2, 3, 4, 5}
fmt.Println(sum(nums...)) // 展开切片
2.5 参数默认值 #
Go不支持参数默认值,但可以使用以下方式模拟:
go
func greet(name string, age ...int) {
a := 0
if len(age) > 0 {
a = age[0]
}
fmt.Printf("%s is %d years old\n", name, a)
}
greet("Tom") // Tom is 0 years old
greet("Tom", 25) // Tom is 25 years old
三、返回值 #
3.1 单返回值 #
go
func add(a, b int) int {
return a + b
}
result := add(1, 2)
3.2 多返回值 #
go
func divmod(a, b int) (int, int) {
return a / b, a % b
}
quotient, remainder := divmod(10, 3)
fmt.Println(quotient, remainder) // 3 1
3.3 忽略返回值 #
使用_忽略不需要的返回值:
go
quotient, _ := divmod(10, 3)
3.4 命名返回值 #
go
func divmod(a, b int) (quotient, remainder int) {
quotient = a / b
remainder = a % b
return // 裸返回
}
q, r := divmod(10, 3)
3.5 命名返回值初始化 #
命名返回值会被初始化为零值:
go
func counter() (count int) {
fmt.Println(count) // 0
count = 10
return
}
四、函数调用 #
4.1 基本调用 #
go
result := add(1, 2)
4.2 调用其他包的函数 #
go
import "fmt"
fmt.Println("Hello")
4.3 方法调用 #
go
type Person struct {
Name string
}
func (p Person) SayHello() {
fmt.Println("Hello, I'm", p.Name)
}
p := Person{Name: "Tom"}
p.SayHello()
五、函数作为值 #
5.1 函数类型 #
函数可以赋值给变量:
go
func add(a, b int) int {
return a + b
}
func main() {
var f func(int, int) int = add
fmt.Println(f(1, 2)) // 3
}
5.2 函数作为参数 #
go
func apply(a, b int, f func(int, int) int) int {
return f(a, b)
}
func main() {
result := apply(1, 2, add)
fmt.Println(result) // 3
}
5.3 函数作为返回值 #
go
func getOperator(op string) func(int, int) int {
switch op {
case "+":
return func(a, b int) int { return a + b }
case "-":
return func(a, b int) int { return a - b }
default:
return nil
}
}
func main() {
add := getOperator("+")
fmt.Println(add(1, 2)) // 3
}
六、实际应用 #
6.1 错误处理模式 #
go
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(result)
6.2 工厂函数 #
go
type Config struct {
Host string
Port int
}
func NewConfig(host string, port int) *Config {
return &Config{
Host: host,
Port: port,
}
}
config := NewConfig("localhost", 8080)
6.3 回调函数 #
go
func processItems(items []string, callback func(string)) {
for _, item := range items {
callback(item)
}
}
processItems([]string{"a", "b", "c"}, func(item string) {
fmt.Println(item)
})
七、最佳实践 #
7.1 函数命名 #
- 使用驼峰命名
- 动词开头表示动作
- 布尔返回值用is/has/can开头
go
func getUser() User {}
func saveUser(u User) error {}
func isValid(s string) bool {}
7.2 参数数量 #
- 参数不宜过多(建议不超过5个)
- 参数多时考虑使用结构体
go
type RequestOptions struct {
Timeout time.Duration
Retry int
Headers map[string]string
}
func request(url string, opts RequestOptions) {}
7.3 错误处理 #
go
func doSomething() error {
if err := step1(); err != nil {
return fmt.Errorf("step1 failed: %w", err)
}
return nil
}
八、总结 #
函数要点:
| 特性 | 说明 |
|---|---|
| 参数 | 值传递,支持可变参数 |
| 返回值 | 支持多返回值,命名返回值 |
| 函数类型 | 函数可以赋值给变量 |
| 高阶函数 | 函数作为参数或返回值 |
关键点:
- 值传递:默认值传递,使用指针修改原值
- 多返回值:Go支持多返回值
- 命名返回值:提高可读性,自动初始化
- 可变参数:使用
...表示 - 函数是一等公民:可以赋值、传递、返回
准备好学习多返回值了吗?让我们进入下一章!
最后更新:2026-03-26