
函数是 Go 程序的基本代码块。使用 func 关键字定义。
特点:
// 标准招式:计算两数之和
func add(x int, y int) int {
return x + y
}
// 简写招式:参数类型一样可以合并
func sub(x, y int) int {
return x - y
}
Go 语言的函数最厉害的地方是:可以返回多个值! 通常用于返回结果和错误信息。

// 定义招式:还我漂漂拳
// 输入:名字 (string)
// 输出:新样貌 (string), 掉落金币 (int)
func 还我漂漂拳(name string) (string, int) {
if name == "如花" {
return "绝世美女", 100
}
return name, 0
}
func main() {
// 接收所有返回值
beauty, gold := 还我漂漂拳("如花")
fmt.Println(beauty, gold)
// 只要美女,不要钱?(使用匿名变量 _ 丢弃)
beauty2, _ := 还我漂漂拳("如花")
fmt.Println(beauty2)
}
返回值可以像参数一样命名,这样在函数里它们就是局部变量,最后直接 return 就行(裸返回)。
// 计算矩形面积和周长
func rectProps(length, width float64) (area, perimeter float64) {
// area 和 perimeter 已经被定义为 float64 类型的变量了
area = length * width
perimeter = (length + width) * 2
return // 自动返回 area 和 perimeter,这叫“裸返回”
}


... 变长参数就是为您准备的。不管您点多少,我都用一个切片兜着!
// 接收任意个 string 类型的菜名
func Order(dishes ...string) {
fmt.Printf("秋香姐点了 %d 道菜:\n", len(dishes))
for _, dish := range dishes {
fmt.Println("🍳 正在做:", dish)
}
}
func main() {
Order("烤鸡翅")
Order("蒸鱼", "红烧肉", "米饭")
}
函数可以没有名字,直接赋值给变量,或者立即执行。这叫匿名函数。如果它还引用了外面的变量,就成了闭包。

func main() {
// 1. 匿名函数赋值给变量
add := func(a, b int) int {
return a + b
}
fmt.Println(add(3, 4))
// 2. 立即执行函数
func(name string) {
fmt.Println("你好," + name)
}("秋香")
// 3. 闭包:函数返回函数
counter := getCounter()
fmt.Println(counter()) // 1
fmt.Println(counter()) // 2
// 变量 i 依然活着!
}
func getCounter() func() int {
i := 0
return func() int {
i++
return i
}
}
defer 关键字让函数在当前函数执行结束前才执行。通常用于关闭文件、解锁等清理工作。


defer 打扫厨房()。不管饭做得怎么样,甚至中间炸了锅(panic),我最后一定会打扫的!
注意: 多个 defer 是后进先出(像压子弹一样)。
func Cooking() {
fmt.Println("🔪 开始切菜")
defer fmt.Println("🧹 打扫厨房 (这句最后执行)")
defer fmt.Println("🗑️ 倒垃圾 (这句倒数第二执行)")
fmt.Println("🍳 开始炒菜")
// 假设这里发生意外 panic,defer 依然会执行
fmt.Println("🍲 上菜")
}
// 输出顺序:切菜 -> 炒菜 -> 上菜 -> 倒垃圾 -> 打扫厨房
看下面的代码,猜猜输出什么?
package main
import "fmt"
func main() {
var fns []func()
for i := 0; i < 3; i++ {
// 注意:闭包捕获的是变量 i 的引用,而不是当时的值!
fns = append(fns, func() {
fmt.Println(i)
})
}
for _, f := range fns {
f()
}
}
任务: 输出结果是 0 1 2 吗?
答案: 3 3 3
解析: 这是一个经典坑!闭包里引用的是变量 i 的地址。循环结束时 i 变成了 3。所有闭包执行时都去读 i,读到的都是 3。
修正: 在循环里写 temp := i,然后闭包用 temp。