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),如果忘了赋值,可能意外返回零值而不报错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 }。但要注意:循环中创建的闭包共享外部变量的引用。
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 里最容易掉进引用陷阱。