Go 语言函数
函数是组织和重用代码的基本单位。Go 语言的函数设计简洁而强大,支持多返回值、命名返回值、可变参数等特性。本章将详细介绍 Go 函数的各种用法。
📋 函数基础
函数声明和定义
go
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)
}函数参数
值传递
go
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)
}切片和映射参数
go
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 // 修改现有元素
}返回值
多返回值
go
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
}命名返回值
go
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("无法解析字符串")
}🔄 可变参数函数
基本可变参数
go
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...)
}高级可变参数用法
go
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
}🎯 函数作为值
函数变量
go
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 }高阶函数
go
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 }🔄 递归函数
基本递归
go
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)
}尾递归优化
go
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)
}🎯 实际应用示例
数学工具库
go
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)
}🎓 小结
本章我们深入学习了 Go 语言的函数:
- ✅ 函数基础:声明、参数、返回值、命名返回值
- ✅ 可变参数:灵活的参数处理
- ✅ 函数值:函数作为一等公民,高阶函数
- ✅ 递归函数:递归原理和尾递归优化
- ✅ 实际应用:数学工具库的实现
函数是Go语言的核心概念,掌握函数的各种用法对于编写高质量的Go代码至关重要。
接下来,我们将学习 Go 语言函数进阶,包括闭包、匿名函数等高级特性。
函数使用建议
- 保持函数简短,专注单一职责
- 使用描述性的函数名和参数名
- 善用多返回值处理错误
- 考虑使用命名返回值提高可读性