Go函数需显式声明参数和返回类型,func后不换行;单返回值省括号,多返回值必用括号;空函数体须有花括号;return须在末尾或显式写出;闭包捕获变量引用需局部固定;函数类型别名不兼容原类型。

Go 函数怎么写才不报错:签名、花括号、return 顺序
Go 要求函数声明必须显式写出所有参数类型和返回类型,且 func 关键字后不能换行(除非用括号包裹多行参数)。常见错误是漏写返回类型,或把 return 放在非末尾位置却没加类型——编译器直接报 missing return at end of function。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 参数列表里每个变量都要带类型,
a int, b string不可简写为a, b int(除非同类型) - 单返回值可省略括号:
func add(a, b int) int;多返回值必须用括号:func split(n int) (int, int) - 哪怕只有一行逻辑,也建议显式写
return,避免控制流意外遗漏 - 空函数体必须有花括号:
func noop() {},不能写成func noop()
函数调用时传参不对?看清楚是指针还是值、命名返回还是匿名
Go 默认按值传递,结构体大了容易性能抖动;但更常踩的坑是:该传 &v 却传了 v,导致修改没生效。另外,命名返回变量会自动声明并初始化,但若中途 return 没赋值,可能返回零值而不报错。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 想修改原变量,参数类型得是
*T,调用时传&v;否则传v就只是副本 - 命名返回(如
func foo() (err error))适合错误处理场景,但别依赖它自动清零——显式赋值更安全 - 调用变参函数(
...T)时,如果已有切片,记得加...展开:fmt.Println(vals...),否则会当做一个参数传进去
闭包捕获变量出问题?重点看循环变量和生命周期
Go 的闭包捕获的是变量的引用,不是快照。在 for 循环里直接用循环变量创建多个闭包,最后它们很可能都指向同一个地址,结果全变成最后一次迭代的值。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 在循环内用局部变量“固定”当前值:
for _, v := range items { v := v; go func() { fmt.Println(v) }() } - 闭包引用外部变量时,要确认该变量不会在闭包执行前被回收——比如函数返回闭包,而闭包引用了栈上已结束的局部变量,就会引发不可预测行为
- 调试时可打印变量地址:
fmt.Printf("%p", &v),验证是否真被复用
函数作为值传递时类型不匹配?接口、类型别名、nil 值要小心
Go 函数类型是严格匹配的:func(int) string 和 func(int) string 看似一样,但如果一个是自定义类型别名(如 type Handler func(int) string),就不能直接赋值给原生类型,哪怕签名完全一致。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 函数类型别名 ≠ 原类型,强制转换需显式:
Handler(f),不能直接h := f - 函数变量可为
nil,调用前务必判空,否则 panic:if fn != nil { fn() } - 往
map或结构体字段存函数时,注意 key 类型或字段类型是否和函数签名一字不差
函数签名里的每个字符都算数,类型别名、指针符号、括号位置、返回变量命名——差一点,编译器就拒绝合作。最常被忽略的是循环中闭包对变量的引用方式,以及函数类型别名带来的隐式不兼容。


















