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:错误处理机制