Go语言的函数是构建程序逻辑的核心单元,具有强大的灵活性和多样性。以下从基础定义到高级特性,全面解析Go函数的设计、使用场景及示例代码。


一、函数基础定义

1.1 基本结构

Go函数使用 func 关键字定义,语法如下:

func 函数名(参数列表) (返回值列表) {
    // 函数体
}
  • 参数列表:可选,用于接收输入值,格式为 参数名 类型
  • 返回值列表:可选,指定函数返回的值类型。若无返回值可省略。
  • 函数体:实现具体逻辑的代码块。

示例:简单加法函数

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

func main() {
    sum := add(3, 5)
    fmt.Println("Sum:", sum) // 输出: Sum: 8
}

二、参数传递方式

2.1 值传递

Go默认使用值传递,即传递参数的副本,函数内修改不会影响原始值。

func modifyValue(num int) {
    num = 10
}

func main() {
    x := 5
    modifyValue(x)
    fmt.Println(x) // 输出: 5(原始值未改变)
}

2.2 引用传递

通过指针实现引用传递,函数内修改会影响原始值。

func modifyReference(num *int) {
    *num = 10
}

func main() {
    y := 5
    modifyReference(&y)
    fmt.Println(y) // 输出: 10(原始值被修改)
}

三、返回值类型

3.1 单个返回值

func square(n int) int {
    return n * n
}

3.2 多个返回值

Go支持返回多个值,常用于返回结果和错误信息。

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

func main() {
    quotient, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Quotient:", quotient) // 输出: Quotient: 5
    }
}

3.3 命名返回值

为返回值命名,简化 return 语句。

func swap(a, b int) (x, y int) {
    x = b
    y = a
    return // 直接返回命名值
}

四、特殊函数类型

4.1 变参函数

使用 ...T 语法接收不定数量的同类型参数。

func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

func main() {
    result := sum(1, 2, 3, 4, 5)
    fmt.Println("Sum:", result) // 输出: Sum: 15
}

4.2 匿名函数

匿名函数无名称,可赋值给变量或立即执行。

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

// 立即执行
result := func(a, b int) int {
    return a * b
}(5, 6)
fmt.Println("Result:", result) // 输出: Result: 30

4.3 闭包

匿名函数可以捕获外部变量,形成闭包。

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

func main() {
    c := counter()
    fmt.Println(c()) // 输出: 1
    fmt.Println(c()) // 输出: 2
}

4.4 defer函数

defer 用于延迟执行函数调用,常用于资源释放。

func main() {
    file, _ := os.Open("file.txt")
    defer file.Close() // 确保文件关闭

    // 读取文件...
}

五、适用场景

5.1 模块化编程

将复杂逻辑封装成函数,提高代码复用性。

// 计算矩形面积
func calculateArea(width, height int) int {
    return width * height
}

5.2 错误处理

多返回值用于返回结果和错误信息。

func parseInput(s string) (int, error) {
    return strconv.Atoi(s)
}

5.3 并发编程

函数作为goroutine执行,实现并发。

func worker(id int) {
    fmt.Printf("Worker %d is working\n", id)
}

func main() {
    for i := 0; i < 5; i++ {
        go worker(i)
    }
    time.Sleep(time.Second) // 等待goroutine完成
}

5.4 资源管理

使用 defer 确保资源释放。

func readData() {
    conn, _ := net.Dial("tcp", "example.com:80")
    defer conn.Close()
    // 使用conn...
}

5.5 高阶函数

函数可作为参数或返回值,实现高阶函数。

func apply(fn func(int) int, x int) int {
    return fn(x)
}

func main() {
    result := apply(func(n int) int {
        return n * 2
    }, 5)
    fmt.Println(result) // 输出: 10
}

六、高级特性

6.1 init函数

init 函数在 main 函数前自动执行,用于包级初始化。

package main

import "fmt"

func init() {
    fmt.Println("Initializing package...")
}

func main() {
    fmt.Println("Main function started.")
}

6.2 包管理

  • 导出函数:首字母大写的函数可被其他包访问。
  • 包别名:使用 import 为包取别名。
import (
    "fmt"
    "math/rand"
    mymath "myproject/mathutils" // 别名
)

func main() {
    fmt.Println(mymath.Add(1, 2)) // 调用自定义包函数
}

6.3 内置函数

  • len():获取长度。
  • new():分配值类型内存。
  • make():分配引用类型内存(如 mapslicechan)。
s := make([]int, 5) // 创建长度为5的slice
p := new(int)       // 分配int指针

七、完整示例

示例1:多返回值与命名返回值

func calc(a, b int) (sum, diff int) {
    sum = a + b
    diff = a - b
    return
}

func main() {
    s, d := calc(10, 3)
    fmt.Println("Sum:", s, "Difference:", d) // 输出: Sum: 13 Difference: 7
}

示例2:闭包与延迟执行

func logger(prefix string) func(string) {
    return func(msg string) {
        fmt.Printf("[%s] %s\n", prefix, msg)
    }
}

func main() {
    log := logger("INFO")
    defer log("Function completed")
    log("Processing started") // 输出: [INFO] Processing started
}

示例3:变参与匿名函数

func main() {
    max := func(values ...int) int {
        var m int
        for _, v := range values {
            if v > m {
                m = v
            }
        }
        return m
    }
    fmt.Println(max(3, 7, 1, 9)) // 输出: 9
}

八、总结

Go语言函数的特性包括:

  • 简洁定义:通过 func 关键字声明。
  • 灵活参数:支持值传递、引用传递、变参。
  • 多返回值:适用于错误处理和多重结果返回。
  • 闭包与高阶函数:提升代码复用性和功能性。
  • 资源管理defer 机制确保资源释放。
  • 包管理:通过首字母大小写控制可见性。