Skip to content

函数和方法

函数定义

基本语法

go
func functionName(param1 type1, param2 type2) returnType {
    // 函数体
    return value
}

示例

go
// 简单函数
func add(a int, b int) int {
    return a + b
}

// 相同类型参数可以简写
func add(a, b int) int {
    return a + b
}

// 无返回值
func printMessage(msg string) {
    fmt.Println(msg)
}

// 多个返回值
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为0")
    }
    return a / b, nil
}

多返回值

Go 语言的函数可以返回多个值,这是 Go 语言的特色之一:

go
// 返回两个值
func swap(a, b string) (string, string) {
    return b, a
}

// 命名返回值
func calculate(a, b int) (sum int, product int) {
    sum = a + b
    product = a * b
    return  // 自动返回命名变量
}

// 使用示例
x, y := swap("hello", "world")
sum, prod := calculate(3, 4)

可变参数

使用 ... 表示可变参数:

go
// 可变参数必须是最后一个参数
func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

// 调用
result := sum(1, 2, 3, 4, 5)
result = sum(1, 2, 3)

// 传递切片
nums := []int{1, 2, 3}
result = sum(nums...)

函数作为值

在 Go 中,函数是一等公民,可以作为值传递:

go
// 函数类型
type Operation func(int, int) int

func add(a, b int) int {
    return a + b
}

func multiply(a, b int) int {
    return a * b
}

// 函数作为参数
func calculate(a, b int, op Operation) int {
    return op(a, b)
}

// 使用
result := calculate(3, 4, add)
result = calculate(3, 4, multiply)

匿名函数和闭包

匿名函数

go
// 立即执行
func() {
    fmt.Println("匿名函数")
}()

// 赋值给变量
add := func(a, b int) int {
    return a + b
}
result := add(3, 4)

闭包

闭包可以访问外部作用域的变量:

go
func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

// 使用
c := counter()
fmt.Println(c())  // 1
fmt.Println(c())  // 2
fmt.Println(c())  // 3

defer 语句

defer 用于延迟执行函数,常用于资源清理:

go
func readFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()  // 函数返回前执行
    
    // 处理文件
    return nil
}

// 多个 defer 按 LIFO 顺序执行
func example() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    // 输出: 3, 2, 1
}

方法

方法是带有接收者的函数。

值接收者

go
type Rectangle struct {
    Width  float64
    Height float64
}

// 值接收者方法
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// 使用
rect := Rectangle{Width: 10, Height: 5}
area := rect.Area()

指针接收者

go
// 指针接收者方法(可以修改接收者)
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

// 使用
rect := Rectangle{Width: 10, Height: 5}
rect.Scale(2)  // rect 被修改

选择值接收者还是指针接收者?

  • 值接收者:当方法不需要修改接收者,或者接收者是小型结构体时使用
  • 指针接收者:当方法需要修改接收者,或者接收者是大型结构体时使用

方法集

go
type Person struct {
    Name string
    Age  int
}

// 值接收者方法
func (p Person) GetName() string {
    return p.Name
}

// 指针接收者方法
func (p *Person) SetAge(age int) {
    p.Age = age
}

// 都可以通过值和指针调用
person := Person{Name: "Alice", Age: 30}
person.GetName()  // OK
(&person).GetName()  // OK

person.SetAge(31)  // OK (自动取地址)
(&person).SetAge(31)  // OK

函数和方法示例

go
package main

import "fmt"

// 普通函数
func greet(name string) string {
    return fmt.Sprintf("Hello, %s!", name)
}

// 多返回值
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为0")
    }
    return a / b, nil
}

// 可变参数
func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

// 结构体和方法
type Calculator struct {
    result int
}

func (c *Calculator) Add(n int) {
    c.result += n
}

func (c Calculator) GetResult() int {
    return c.result
}

func main() {
    // 函数调用
    msg := greet("Go")
    fmt.Println(msg)
    
    // 多返回值
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("结果:", result)
    }
    
    // 可变参数
    total := sum(1, 2, 3, 4, 5)
    fmt.Println("总和:", total)
    
    // 方法调用
    calc := Calculator{}
    calc.Add(10)
    calc.Add(20)
    fmt.Println("计算结果:", calc.GetResult())
}

下一步

接下来我们将学习:

基于 VitePress 构建