Go Functions

Functions are the basic unit for organizing and reusing code. Go's function design is concise yet powerful, supporting multiple return values, named return values, variadic parameters, and more. This chapter covers the various ways to use Go functions in detail.

📋 Function Basics

Function Declaration and Definition

package main

import "fmt"

// 基本函数语法: func 函数名(参数列表) 返回类型 { 函数体 }
func greet() {
    fmt.Println("Hello, World!")
}

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

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

// 多个参数,多个返回值
func calculate(a, b int) (int, int, int, int) {
    return a + b, a - b, a * b, a / b
}

func main() {
    // 调用函数
    greet()
    greetPerson("Go")
    
    result := add(5, 3)
    fmt.Printf("5 + 3 = %d\n", result)
    
    sum, diff, product, quotient := calculate(20, 4)
    fmt.Printf("20 和 4 的运算结果: 和=%d, 差=%d, 积=%d, 商=%d\n", 
               sum, diff, product, quotient)
}

Function Parameters

Pass by Value

func main() {
    // Go 语言是值传递
    x := 10
    fmt.Printf("调用前 x = %d\n", x)
    
    modifyValue(x)
    fmt.Printf("调用后 x = %d\n", x)  // x 仍然是 10
    
    // 如果需要修改原值,需要传递指针
    fmt.Printf("调用指针函数前 x = %d\n", x)
    modifyPointer(&x)
    fmt.Printf("调用指针函数后 x = %d\n", x)  // x 变成了 20
}

func modifyValue(num int) {
    num = 100
    fmt.Printf("函数内 num = %d\n", num)
}

func modifyPointer(num *int) {
    *num = 20
    fmt.Printf("函数内 *num = %d\n", *num)
}

Slice and Map Parameters

func main() {
    // 切片是引用类型,修改会影响原切片
    numbers := []int{1, 2, 3, 4, 5}
    fmt.Printf("修改前: %v\n", numbers)
    
    modifySlice(numbers)
    fmt.Printf("修改后: %v\n", numbers)
    
    // 映射也是引用类型
    scores := map[string]int{"Alice": 85, "Bob": 92}
    fmt.Printf("修改前: %v\n", scores)
    
    modifyMap(scores)
    fmt.Printf("修改后: %v\n", scores)
}

func modifySlice(slice []int) {
    slice[0] = 100  // 修改第一个元素
    slice = append(slice, 6, 7, 8)  // 注意:append 可能不会影响原切片
}

func modifyMap(m map[string]int) {
    m["Charlie"] = 78  // 添加新元素
    m["Alice"] = 95    // 修改现有元素
}

Return Values

Multiple Return Values

import (
    "errors"
    "fmt"
    "math"
)

func main() {
    // 处理多返回值
    quotient, remainder, err := divide(10, 3)
    if err != nil {
        fmt.Printf("错误: %v\n", err)
    } else {
        fmt.Printf("10 ÷ 3 = %d%d\n", quotient, remainder)
    }
    
    // 忽略某些返回值
    _, remainder2, _ := divide(17, 5)
    fmt.Printf("17 除以 5 的余数: %d\n", remainder2)
    
    // 数学运算函数
    result, isValid := sqrt(16)
    if isValid {
        fmt.Printf("√16 = %.2f\n", result)
    }
    
    result2, isValid2 := sqrt(-4)
    if !isValid2 {
        fmt.Println("负数没有实数平方根")
    }
}

func divide(a, b int) (int, int, error) {
    if b == 0 {
        return 0, 0, errors.New("除数不能为零")
    }
    return a / b, a % b, nil
}

func sqrt(x float64) (float64, bool) {
    if x < 0 {
        return 0, false
    }
    return math.Sqrt(x), true
}

Named Return Values

func main() {
    // 使用命名返回值的函数
    area, perimeter := rectangleCalculations(5, 3)
    fmt.Printf("矩形面积: %.2f, 周长: %.2f\n", area, perimeter)
    
    // 错误处理示例
    result, err := parseAndCalculate("10", "5")
    if err != nil {
        fmt.Printf("错误: %v\n", err)
    } else {
        fmt.Printf("结果: %d\n", result)
    }
}

// 命名返回值
func rectangleCalculations(length, width float64) (area, perimeter float64) {
    area = length * width
    perimeter = 2 * (length + width)
    return  // 不需要指定返回值,会自动返回命名的变量
}

// 命名返回值在错误处理中很有用
func parseAndCalculate(aStr, bStr string) (result int, err error) {
    var a, b int
    
    // 解析第一个数字
    if a, err = parseInt(aStr); err != nil {
        return  // 相当于 return 0, err
    }
    
    // 解析第二个数字
    if b, err = parseInt(bStr); err != nil {
        return
    }
    
    result = a + b
    return  // 相当于 return result, nil
}

func parseInt(s string) (int, error) {
    // 简单的字符串转整数实现
    if s == "10" {
        return 10, nil
    } else if s == "5" {
        return 5, nil
    }
    return 0, errors.New("无法解析字符串")
}

🔄 Variadic Functions

Basic Variadic Parameters

func main() {
    // 可变参数函数调用
    fmt.Printf("无参数调用: %d\n", sum())
    fmt.Printf("单个参数: %d\n", sum(5))
    fmt.Printf("多个参数: %d\n", sum(1, 2, 3, 4, 5))
    
    // 传递切片给可变参数函数
    numbers := []int{10, 20, 30, 40}
    fmt.Printf("传递切片: %d\n", sum(numbers...))  // 使用 ... 展开切片
    
    // 字符串连接示例
    message := concatenate("Hello", " ", "Go", " ", "World", "!")
    fmt.Printf("连接结果: %s\n", message)
    
    // 格式化消息
    formattedMsg := formatMessage("用户 %s 的分数是 %d", "Alice", 95)
    fmt.Println(formattedMsg)
}

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

// 字符串可变参数
func concatenate(strings ...string) string {
    result := ""
    for _, str := range strings {
        result += str
    }
    return result
}

// 混合参数(固定参数 + 可变参数)
func formatMessage(format string, args ...interface{}) string {
    // 简单的格式化实现
    return fmt.Sprintf(format, args...)
}

Advanced Variadic Usage

import "reflect"

func main() {
    // 类型安全的可变参数处理
    printInts(1, 2, 3, 4, 5)
    printStrings("Hello", "World", "Go")
    
    // 通用打印函数
    printValues("混合类型:", 42, "Hello", 3.14, true)
    
    // 统计函数
    stats := calculateStats(85, 92, 78, 96, 88, 91)
    fmt.Printf("统计结果: %+v\n", stats)
}

func printInts(numbers ...int) {
    fmt.Print("整数: ")
    for i, num := range numbers {
        if i > 0 {
            fmt.Print(", ")
        }
        fmt.Print(num)
    }
    fmt.Println()
}

func printStrings(strings ...string) {
    fmt.Print("字符串: ")
    for i, str := range strings {
        if i > 0 {
            fmt.Print(", ")
        }
        fmt.Printf("\"%s\"", str)
    }
    fmt.Println()
}

// 处理任意类型的可变参数
func printValues(prefix string, values ...interface{}) {
    fmt.Print(prefix + " ")
    for i, value := range values {
        if i > 0 {
            fmt.Print(", ")
        }
        fmt.Printf("%v(%T)", value, value)
    }
    fmt.Println()
}

// 统计数据结构
type Statistics struct {
    Count   int
    Sum     float64
    Average float64
    Min     float64
    Max     float64
}

func calculateStats(values ...float64) Statistics {
    if len(values) == 0 {
        return Statistics{}
    }
    
    stats := Statistics{
        Count: len(values),
        Min:   values[0],
        Max:   values[0],
    }
    
    for _, value := range values {
        stats.Sum += value
        if value < stats.Min {
            stats.Min = value
        }
        if value > stats.Max {
            stats.Max = value
        }
    }
    
    stats.Average = stats.Sum / float64(stats.Count)
    return stats
}

🎯 Functions as Values

Function Variables

import "math"

func main() {
    // 函数可以赋值给变量
    var operation func(float64, float64) float64
    
    operation = add_float
    fmt.Printf("加法: %.2f\n", operation(3.5, 2.1))
    
    operation = multiply_float
    fmt.Printf("乘法: %.2f\n", operation(3.5, 2.1))
    
    // 函数切片
    operations := []func(float64, float64) float64{
        add_float,
        subtract_float,
        multiply_float,
        divide_float,
    }
    
    operationNames := []string{"加法", "减法", "乘法", "除法"}
    
    a, b := 10.0, 3.0
    for i, op := range operations {
        result := op(a, b)
        fmt.Printf("%.1f %s %.1f = %.2f\n", a, operationNames[i], b, result)
    }
    
    // 函数映射
    calculator := map[string]func(float64, float64) float64{
        "+": add_float,
        "-": subtract_float,
        "*": multiply_float,
        "/": divide_float,
        "^": math.Pow,
    }
    
    fmt.Println("\n计算器演示:")
    expressions := []struct {
        a, b float64
        op   string
    }{
        {10, 5, "+"},
        {10, 5, "-"},
        {10, 5, "*"},
        {10, 5, "/"},
        {2, 8, "^"},
    }
    
    for _, expr := range expressions {
        if fn, exists := calculator[expr.op]; exists {
            result := fn(expr.a, expr.b)
            fmt.Printf("%.1f %s %.1f = %.2f\n", expr.a, expr.op, expr.b, result)
        }
    }
}

func add_float(a, b float64) float64      { return a + b }
func subtract_float(a, b float64) float64 { return a - b }
func multiply_float(a, b float64) float64 { return a * b }
func divide_float(a, b float64) float64   { return a / b }

Higher-Order Functions

func main() {
    // 高阶函数:接受函数作为参数
    numbers := []int{1, 2, 3, 4, 5}
    
    // 应用不同的变换函数
    squared := applyTransform(numbers, square)
    fmt.Printf("平方: %v\n", squared)
    
    doubled := applyTransform(numbers, double)
    fmt.Printf("翻倍: %v\n", doubled)
    
    cubed := applyTransform(numbers, func(x int) int { return x * x * x })
    fmt.Printf("立方: %v\n", cubed)
    
    // 过滤函数
    evens := filter(numbers, isEven)
    fmt.Printf("偶数: %v\n", evens)
    
    odds := filter(numbers, isOdd)
    fmt.Printf("奇数: %v\n", odds)
    
    // 归约函数
    sum := reduce(numbers, 0, add_int)
    fmt.Printf("总和: %d\n", sum)
    
    product := reduce(numbers, 1, multiply_int)
    fmt.Printf("乘积: %d\n", product)
    
    // 复合函数
    addThenSquare := compose(square, func(x int) int { return x + 1 })
    result := addThenSquare(5)  // (5+1)^2 = 36
    fmt.Printf("先加1再平方: %d\n", result)
}

// 变换函数:对切片中每个元素应用函数
func applyTransform(slice []int, fn func(int) int) []int {
    result := make([]int, len(slice))
    for i, v := range slice {
        result[i] = fn(v)
    }
    return result
}

// 过滤函数:根据条件过滤元素
func filter(slice []int, predicate func(int) bool) []int {
    var result []int
    for _, v := range slice {
        if predicate(v) {
            result = append(result, v)
        }
    }
    return result
}

// 归约函数:将切片归约为单个值
func reduce(slice []int, initial int, fn func(int, int) int) int {
    result := initial
    for _, v := range slice {
        result = fn(result, v)
    }
    return result
}

// 函数组合
func compose(f, g func(int) int) func(int) int {
    return func(x int) int {
        return f(g(x))
    }
}

// 辅助函数
func square(x int) int         { return x * x }
func double(x int) int         { return x * 2 }
func isEven(x int) bool        { return x%2 == 0 }
func isOdd(x int) bool         { return x%2 != 0 }
func add_int(a, b int) int     { return a + b }
func multiply_int(a, b int) int { return a * b }

🔄 Recursive Functions

Basic Recursion

func main() {
    // 阶乘计算
    for i := 0; i <= 10; i++ {
        fmt.Printf("%d! = %d\n", i, factorial(i))
    }
    
    // 斐波那契数列
    fmt.Println("\n斐波那契数列:")
    for i := 0; i <= 15; i++ {
        fmt.Printf("fib(%d) = %d\n", i, fibonacci(i))
    }
    
    // 汉诺塔问题
    fmt.Println("\n汉诺塔移动步骤 (3个盘子):")
    hanoi(3, "A", "C", "B")
}

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

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

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

Tail Recursion Optimization

func main() {
    // 普通递归 vs 尾递归
    fmt.Printf("普通递归阶乘 10! = %d\n", factorial(10))
    fmt.Printf("尾递归阶乘 10! = %d\n", factorialTail(10))
    
    // 尾递归斐波那契
    fmt.Printf("尾递归斐波那契 fib(15) = %d\n", fibonacciTail(15))
}

// 尾递归阶乘
func factorialTail(n int) int {
    return factorialHelper(n, 1)
}

func factorialHelper(n, acc int) int {
    if n <= 1 {
        return acc
    }
    return factorialHelper(n-1, n*acc)
}

// 尾递归斐波那契
func fibonacciTail(n int) int {
    return fibonacciHelper(n, 0, 1)
}

func fibonacciHelper(n, a, b int) int {
    if n == 0 {
        return a
    }
    if n == 1 {
        return b
    }
    return fibonacciHelper(n-1, b, a+b)
}

🎯 Practical Examples

Math Utility Library

import "math"

// 数学工具包
type MathUtils struct{}

func NewMathUtils() *MathUtils {
    return &MathUtils{}
}

func main() {
    math := NewMathUtils()
    
    // 几何计算
    fmt.Printf("圆形面积 (半径5): %.2f\n", math.CircleArea(5))
    fmt.Printf("矩形面积 (5x3): %.2f\n", math.RectangleArea(5, 3))
    fmt.Printf("三角形面积 (底5高4): %.2f\n", math.TriangleArea(5, 4))
    
    // 数值计算
    fmt.Printf("最大公约数 (48, 18): %d\n", math.GCD(48, 18))
    fmt.Printf("最小公倍数 (48, 18): %d\n", math.LCM(48, 18))
    fmt.Printf("是否为素数 (17): %t\n", math.IsPrime(17))
    fmt.Printf("是否为素数 (18): %t\n", math.IsPrime(18))
    
    // 统计计算
    data := []float64{85, 92, 78, 96, 88, 91, 79, 95}
    fmt.Printf("平均值: %.2f\n", math.Mean(data))
    fmt.Printf("中位数: %.2f\n", math.Median(data))
    fmt.Printf("标准差: %.2f\n", math.StandardDeviation(data))
}

// 几何计算函数
func (m *MathUtils) CircleArea(radius float64) float64 {
    return math.Pi * radius * radius
}

func (m *MathUtils) RectangleArea(length, width float64) float64 {
    return length * width
}

func (m *MathUtils) TriangleArea(base, height float64) float64 {
    return 0.5 * base * height
}

// 数论函数
func (m *MathUtils) GCD(a, b int) int {
    for b != 0 {
        a, b = b, a%b
    }
    return a
}

func (m *MathUtils) LCM(a, b int) int {
    return (a * b) / m.GCD(a, b)
}

func (m *MathUtils) IsPrime(n int) bool {
    if n < 2 {
        return false
    }
    if n == 2 {
        return true
    }
    if n%2 == 0 {
        return false
    }
    for i := 3; i*i <= n; i += 2 {
        if n%i == 0 {
            return false
        }
    }
    return true
}

// 统计函数
func (m *MathUtils) Mean(data []float64) float64 {
    if len(data) == 0 {
        return 0
    }
    sum := 0.0
    for _, v := range data {
        sum += v
    }
    return sum / float64(len(data))
}

func (m *MathUtils) Median(data []float64) float64 {
    if len(data) == 0 {
        return 0
    }
    
    // 复制并排序数据
    sorted := make([]float64, len(data))
    copy(sorted, data)
    
    // 简单排序
    for i := 0; i < len(sorted)-1; i++ {
        for j := i + 1; j < len(sorted); j++ {
            if sorted[i] > sorted[j] {
                sorted[i], sorted[j] = sorted[j], sorted[i]
            }
        }
    }
    
    n := len(sorted)
    if n%2 == 0 {
        return (sorted[n/2-1] + sorted[n/2]) / 2
    }
    return sorted[n/2]
}

func (m *MathUtils) StandardDeviation(data []float64) float64 {
    if len(data) <= 1 {
        return 0
    }
    
    mean := m.Mean(data)
    sumSquaredDiff := 0.0
    
    for _, v := range data {
        diff := v - mean
        sumSquaredDiff += diff * diff
    }
    
    variance := sumSquaredDiff / float64(len(data)-1)
    return math.Sqrt(variance)
}

🎓 Summary

In this chapter, we explored Go functions in depth:

  • Function basics: declaration, parameters, return values, named return values
  • Variadic parameters: flexible parameter handling
  • Function values: functions as first-class citizens, higher-order functions
  • Recursive functions: recursion principles and tail recursion optimization
  • Practical applications: implementing a math utility library

Functions are a core concept in Go. Mastering their various uses is essential for writing high-quality Go code.


Next, we will learn Advanced Go Functions, including closures, anonymous functions, and other advanced features.

::: tip Function Usage Tips

  • Keep functions short and focused on a single responsibility
  • Use descriptive function and parameter names
  • Leverage multiple return values for error handling
  • Consider named return values to improve readability :::