Skip to content
<

Golang 函数与方法

函数基础

函数定义

go
package main

import "fmt"

// 基本函数
func sayHello() {
    fmt.Println("Hello, World!")
}

// 带参数的函数
func greet(name string) {
    fmt.Printf("Hello, %s!\n", name)
}

// 带返回值的函数
func add(a int, b int) int {
    return a + b
}

// 参数类型相同时的简写
func multiply(a, b int) int {
    return a * b
}

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

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

函数调用

go
func functionDemo() {
    // 无参数无返回值
    sayHello()

    // 带参数
    greet("Jackson")

    // 带返回值
    result := add(10, 20)
    fmt.Println("10 + 20 =", result)

    // 多返回值
    quotient, err := divide(10, 2)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("10 / 2 =", quotient)
    }

    // 忽略某个返回值
    q, _ := divide(20, 4)
    fmt.Println("20 / 4 =", q)

    // 命名返回值
    s, p := calculate(5, 3)
    fmt.Printf("5 + 3 = %d, 5 × 3 = %d\n", s, p)
}

可变参数

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

// 混合参数
func printInfo(prefix string, values ...interface{}) {
    fmt.Print(prefix, ": ")
    for _, v := range values {
        fmt.Printf("%v ", v)
    }
    fmt.Println()
}

func variadicDemo() {
    // 调用可变参数函数
    fmt.Println("sum(1, 2, 3) =", sum(1, 2, 3))
    fmt.Println("sum(1, 2, 3, 4, 5) =", sum(1, 2, 3, 4, 5))

    // 传递切片
    numbers := []int{10, 20, 30, 40}
    fmt.Println("sum(numbers...) =", sum(numbers...))

    // 混合参数
    printInfo("数据", 1, "hello", 3.14, true)
}

匿名函数与闭包

匿名函数

go
func anonymousDemo() {
    // 定义并立即调用
    func() {
        fmt.Println("这是一个匿名函数")
    }()

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

    // 作为参数传递
    calculate := func(a, b int, op func(int, int) int) int {
        return op(a, b)
    }

    result := calculate(10, 5, func(x, y int) int {
        return x - y
    })
    fmt.Println("10 - 5 =", result)
}

闭包

go
// 闭包:函数引用外部变量
func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

func fibonacci() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}

func closureDemo() {
    // 计数器闭包
    c1 := counter()
    fmt.Println("c1:", c1()) // 1
    fmt.Println("c1:", c1()) // 2
    fmt.Println("c1:", c1()) // 3

    c2 := counter()
    fmt.Println("c2:", c2()) // 1
    fmt.Println("c2:", c2()) // 2

    // 斐波那契闭包
    fmt.Println("\n斐波那契数列:")
    fib := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Printf("%d ", fib())
    }
    fmt.Println()
}

高阶函数

go
// 函数作为参数
func apply(numbers []int, fn func(int) int) []int {
    result := make([]int, len(numbers))
    for i, num := range numbers {
        result[i] = fn(num)
    }
    return result
}

// 函数作为返回值
func makeMultiplier(factor int) func(int) int {
    return func(x int) int {
        return x * factor
    }
}

func higherOrderDemo() {
    numbers := []int{1, 2, 3, 4, 5}

    // 每个元素乘以2
    doubled := apply(numbers, func(x int) int {
        return x * 2
    })
    fmt.Println("翻倍:", doubled)

    // 每个元素平方
    squared := apply(numbers, func(x int) int {
        return x * x
    })
    fmt.Println("平方:", squared)

    // 创建乘法器
    double := makeMultiplier(2)
    triple := makeMultiplier(3)

    fmt.Println("double(5) =", double(5))
    fmt.Println("triple(5) =", triple(5))
}

递归函数

go
// 阶乘
func factorial(n int) int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n-1)
}

// 斐波那契数列
func fib(n int) int {
    if n <= 1 {
        return n
    }
    return fib(n-1) + fib(n-2)
}

// 汉诺塔
func hanoi(n int, from, to, aux string) {
    if n == 1 {
        fmt.Printf("移动盘子 1 从 %s%s\n", from, to)
        return
    }
    hanoi(n-1, from, aux, to)
    fmt.Printf("移动盘子 %d%s%s\n", n, from, to)
    hanoi(n-1, aux, to, from)
}

func recursionDemo() {
    // 阶乘
    fmt.Println("5! =", factorial(5))

    // 斐波那契
    fmt.Print("斐波那契数列前10项: ")
    for i := 0; i < 10; i++ {
        fmt.Printf("%d ", fib(i))
    }
    fmt.Println()

    // 汉诺塔
    fmt.Println("\n汉诺塔问题(3个盘子):")
    hanoi(3, "A", "C", "B")
}

方法(Methods)

方法是作用于特定类型的函数。

go
// 定义结构体
type Rectangle struct {
    Width  float64
    Height float64
}

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

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

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

func (r *Rectangle) SetWidth(width float64) {
    r.Width = width
}

// 自定义类型的方法
type MyInt int

func (m MyInt) IsEven() bool {
    return m%2 == 0
}

func (m MyInt) Double() MyInt {
    return m * 2
}

func methodDemo() {
    rect := Rectangle{Width: 10, Height: 5}

    // 调用值接收者方法
    fmt.Printf("面积: %.2f\n", rect.Area())
    fmt.Printf("周长: %.2f\n", rect.Perimeter())

    // 调用指针接收者方法
    rect.Scale(2)
    fmt.Printf("放大后 - 宽: %.2f, 高: %.2f\n", rect.Width, rect.Height)

    rect.SetWidth(20)
    fmt.Printf("设置宽度后 - 宽: %.2f\n", rect.Width)

    // 自定义类型方法
    var num MyInt = 10
    fmt.Printf("%d 是偶数: %t\n", num, num.IsEven())
    fmt.Printf("%d 的两倍: %d\n", num, num.Double())
}

方法值与方法表达式

go
func methodValueDemo() {
    rect := Rectangle{Width: 10, Height: 5}

    // 方法值(绑定到特定实例)
    areaFunc := rect.Area
    fmt.Println("方法值调用:", areaFunc())

    // 方法表达式(需要传入接收者)
    areaExpr := Rectangle.Area
    fmt.Println("方法表达式调用:", areaExpr(rect))

    // 指针接收者的方法表达式
    scaleExpr := (*Rectangle).Scale
    scaleExpr(&rect, 2)
    fmt.Printf("放大后面积: %.2f\n", rect.Area())
}

defer、panic 和 recover

go
func deferPanicRecover() {
    // defer 延迟执行
    defer fmt.Println("函数结束")

    // 使用 defer 进行资源清理
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到 panic:", r)
        }
    }()

    fmt.Println("开始执行")

    // 触发 panic
    // panic("发生错误")

    fmt.Println("正常执行")
}

// 实用的错误处理模式
func safeDivide(a, b float64) (result float64, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("panic: %v", r)
        }
    }()

    if b == 0 {
        panic("除数不能为0")
    }

    result = a / b
    return
}

完整示例:计算器

go
package main

import (
    "fmt"
    "math"
)

type Calculator struct {
    history []string
}

// 加法
func (c *Calculator) Add(a, b float64) float64 {
    result := a + b
    c.addHistory(fmt.Sprintf("%.2f + %.2f = %.2f", a, b, result))
    return result
}

// 减法
func (c *Calculator) Subtract(a, b float64) float64 {
    result := a - b
    c.addHistory(fmt.Sprintf("%.2f - %.2f = %.2f", a, b, result))
    return result
}

// 乘法
func (c *Calculator) Multiply(a, b float64) float64 {
    result := a * b
    c.addHistory(fmt.Sprintf("%.2f × %.2f = %.2f", a, b, result))
    return result
}

// 除法
func (c *Calculator) Divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为0")
    }
    result := a / b
    c.addHistory(fmt.Sprintf("%.2f ÷ %.2f = %.2f", a, b, result))
    return result, nil
}

// 幂运算
func (c *Calculator) Power(base, exp float64) float64 {
    result := math.Pow(base, exp)
    c.addHistory(fmt.Sprintf("%.2f ^ %.2f = %.2f", base, exp, result))
    return result
}

// 添加历史记录
func (c *Calculator) addHistory(record string) {
    c.history = append(c.history, record)
}

// 显示历史记录
func (c *Calculator) ShowHistory() {
    fmt.Println("\n=== 计算历史 ===")
    for i, record := range c.history {
        fmt.Printf("%d. %s\n", i+1, record)
    }
}

// 清除历史
func (c *Calculator) ClearHistory() {
    c.history = []string{}
    fmt.Println("历史记录已清除")
}

func main() {
    calc := &Calculator{}

    fmt.Println("=== 计算器示例 ===")
    fmt.Printf("10 + 5 = %.2f\n", calc.Add(10, 5))
    fmt.Printf("10 - 5 = %.2f\n", calc.Subtract(10, 5))
    fmt.Printf("10 × 5 = %.2f\n", calc.Multiply(10, 5))

    result, err := calc.Divide(10, 5)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Printf("10 ÷ 5 = %.2f\n", result)
    }

    fmt.Printf("2 ^ 8 = %.2f\n", calc.Power(2, 8))

    // 显示历史记录
    calc.ShowHistory()
}

小结

  • 函数定义:支持多返回值、命名返回值
  • 可变参数:使用 ... 语法
  • 匿名函数:可以赋值给变量或作为参数
  • 闭包:函数可以引用外部变量
  • 高阶函数:函数作为参数或返回值
  • 递归:函数调用自身
  • 方法:绑定到特定类型的函数
  • 值接收者 vs 指针接收者:是否需要修改接收者
  • defer:延迟执行,常用于资源清理
  • panic/recover:错误处理机制