Go函数声明必须显式标注所有参数和返回类型,不支持类型推导;变参仅能有一个且须为最后一个;函数是一等公民,但闭包捕获变量引用而非值。

函数声明必须显式写出所有参数类型和返回类型
Go 不支持类型推导或默认参数,每个参数和返回值的类型都得写清楚,不能省略。比如 func add(a, b int) int 是合法的,但 func add(a, b) int 或 func add(a, b int)(无返回类型)会直接报错 missing return 或 expected type。
- 多个同类型参数可简写为
func f(a, b, c string) bool,但不能跨类型混写 - 如果函数不返回任何值,返回类型部分必须写成
func f() {},不能省略括号后的部分 - 返回多个值时,类型列表必须用括号包裹:
func split(n int) (int, int)
命名返回值会让代码更清晰,但要小心“零值陷阱”
你可以给返回值起名字,比如 func divide(a, b float64) (result float64, err error)。这样函数体内可以直接对 result 和 err 赋值,且在 return 语句不带参数时,会自动返回这些变量的当前值(即“裸返回”)。
- 裸返回只在有命名返回值时才有效,否则
return必须带值 - 命名返回值在函数入口处就被初始化为对应类型的零值(
0、""、nil),如果忘了赋值,可能意外返回零值而不报错 - 在 defer 中访问命名返回值能看到其被修改前/后的值,这点常被用于日志或错误包装
变参函数只能有一个,且必须是最后一个参数
Go 用 ... 表示变参,例如 func sum(nums ...int) int。它本质是把参数转成一个切片,所以调用时可以传 sum(1, 2, 3),也可以传 sum(nums...)(注意末尾的 ... 展开语法)。
-
...前的类型不能省略,且该参数必须位于参数列表最右端 - 不能定义像
func f(x ...int, y string)这样的函数,编译直接失败 - 变参参数在函数内就是普通切片,可用
len()、range等操作;但无法直接将数组传入,除非显式转成切片或用...展开
函数是一等公民,但闭包捕获的是变量引用而非快照
Go 支持把函数赋值给变量、作为参数传递、从函数返回,例如 var f func(int) int = func(x int) int { return x * 2 }。但要注意:循环中创建的闭包共享外部变量的引用。
立即学习“go语言免费学习笔记(深入)”;
for i := 0; i < 3; i++ {
defer func() {
fmt.Println(i) // 全部输出 3,不是 0/1/2
}()
}- 常见修复方式是把循环变量作为参数传入匿名函数:
defer func(v int) { fmt.Println(v) }(i) - 函数值比较时,只有
nil函数能相互比较相等,两个非 nil 函数值永远不等(即使逻辑相同) - 方法表达式(如
T.M)和方法值(如t.M)行为不同:前者需要显式传接收者,后者已绑定
函数签名里每个位置的类型都不能含糊,命名返回值看着方便,实际调试时容易因零值掩盖逻辑遗漏;变参看着灵活,但展开和接收的写法稍有不慎就 panic;闭包看似简单,但在循环和 goroutine 里最容易掉进引用陷阱。










