函数基础 #

一、函数定义 #

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
}

八、总结 #

函数要点:

特性 说明
参数 值传递,支持可变参数
返回值 支持多返回值,命名返回值
函数类型 函数可以赋值给变量
高阶函数 函数作为参数或返回值

关键点:

  1. 值传递:默认值传递,使用指针修改原值
  2. 多返回值:Go支持多返回值
  3. 命名返回值:提高可读性,自动初始化
  4. 可变参数:使用...表示
  5. 函数是一等公民:可以赋值、传递、返回

准备好学习多返回值了吗?让我们进入下一章!

最后更新:2026-03-26