函数参数与返回值

本章深入讲解 Go 函数的参数传递和返回值处理。

参数传递方式

值传递

Go 默认使用值传递,函数内修改不影响原值:

package main

import "fmt"

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

func main() {
    x := 10
    modify(x)
    fmt.Printf("函数外: %d\n", x)
}

输出:

函数内: 100
函数外: 10

指针传递

使用指针可以修改原值:

package main

import "fmt"

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

func main() {
    x := 10
    modify(&x)
    fmt.Printf("函数外: %d\n", x)
}

输出:

函数内: 100
函数外: 100

切片传递

切片是引用类型,函数内修改会影响原切片:

package main

import "fmt"

func modifySlice(s []int) {
    s[0] = 100
}

func main() {
    nums := []int{1, 2, 3}
    modifySlice(nums)
    fmt.Printf("nums: %v\n", nums)
}

Map 传递

Map 也是引用类型:

package main

import "fmt"

func modifyMap(m map[string]int) {
    m["new"] = 100
}

func main() {
    m := map[string]int{"one": 1}
    modifyMap(m)
    fmt.Printf("m: %v\n", m)
}

可变参数

基本用法

package main

import "fmt"

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

func main() {
    fmt.Println(sum(1))
    fmt.Println(sum(1, 2))
    fmt.Println(sum(1, 2, 3))
}

可变参数与固定参数

可变参数必须放在最后:

package main

import "fmt"

func printInfo(name string, scores ...int) {
    fmt.Printf("姓名: %s, 成绩: %v\n", name, scores)
}

func main() {
    printInfo("张三", 90, 85, 88)
}

传递切片

使用 ... 展开切片:

package main

import "fmt"

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

func main() {
    nums := []int{1, 2, 3, 4, 5}
    fmt.Println(sum(nums...))
}

任意类型可变参数

使用 interface{} 接收任意类型:

package main

import "fmt"

func printAll(values ...interface{}) {
    for _, v := range values {
        fmt.Printf("值: %v, 类型: %T\n", v, v)
    }
}

func main() {
    printAll(1, "hello", 3.14, true)
}

命名返回值

基本用法

package main

import "fmt"

func divide(a, b int) (quotient, remainder int) {
    quotient = a / b
    remainder = a % b
    return
}

func main() {
    q, r := divide(10, 3)
    fmt.Printf("商: %d, 余数: %d\n", q, r)
}

裸返回

命名返回值可以直接使用 return

package main

import "fmt"

func getName() (firstName, lastName string) {
    firstName = "张"
    lastName = "三"
    return
}

func main() {
    first, last := getName()
    fmt.Printf("姓名: %s%s\n", first, last)
}

多返回值

返回值与错误

Go 常用多返回值处理错误:

package main

import (
    "errors"
    "fmt"
)

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

func main() {
    result, err := divide(10, 3)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    fmt.Printf("结果: %.2f\n", result)

    result, err = divide(10, 0)
    if err != nil {
        fmt.Println("错误:", err)
    }
}

返回多个值

package main

import "fmt"

func getStats(nums []int) (min, max, sum int) {
    if len(nums) == 0 {
        return
    }
    min, max = nums[0], nums[0]
    for _, num := range nums {
        if num < min {
            min = num
        }
        if num > max {
            max = num
        }
        sum += num
    }
    return
}

func main() {
    nums := []int{3, 1, 4, 1, 5, 9, 2, 6}
    min, max, sum := getStats(nums)
    fmt.Printf("最小值: %d, 最大值: %d, 总和: %d\n", min, max, sum)
}

函数作为参数

package main

import "fmt"

func calculate(a, b int, op func(int, int) int) int {
    return op(a, b)
}

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

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

func main() {
    fmt.Printf("加法: %d\n", calculate(10, 5, add))
    fmt.Printf("乘法: %d\n", calculate(10, 5, multiply))

    fmt.Printf("匿名函数: %d\n", calculate(10, 5, func(a, b int) int {
        return a - b
    }))
}

函数作为返回值

package main

import "fmt"

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 }
    case "*":
        return func(a, b int) int { return a * b }
    default:
        return nil
    }
}

func main() {
    add := getOperator("+")
    fmt.Printf("10 + 5 = %d\n", add(10, 5))

    sub := getOperator("-")
    fmt.Printf("10 - 5 = %d\n", sub(10, 5))
}

总结

本章学习了 Go 函数的参数和返回值:

知识点说明
值传递默认方式,复制值
指针传递传递地址,可修改原值
可变参数...类型,接收多个参数
命名返回值为返回值命名,可裸返回
多返回值Go 特性,常用于错误处理