一、函数基础声明规则
1.1 完整函数语法结构
Go函数标准声明格式,包含四大核心组成:函数名、形参列表、返回值列表(可省略)、函数体。
func name(parameter-list) (result-list) { body // 函数逻辑体 }
1.2 核心语法规则
-
返回值括号省略规则:若函数无返回值、或返回无名变量,可省略返回值列表的括号。
-
return强制规则 :函数声明了返回值列表时,必须以
return语句结尾;仅函数逻辑无法执行到末尾时例外。 -
参数类型简写规则:多个连续形参/返回值类型相同时,无需逐个声明类型,统一在末尾声明即可。
1.3 函数签名(函数类型)
-
函数签名由形参类型列表、返回值类型列表唯一决定。
-
形参名、返回值名不影响函数签名,也不影响参数类型简写规则。
-
两个函数的参数类型、返回值类型一一对应,即为相同签名。
1.4 函数调用与参数传递
-
传参顺序:函数调用必须严格按照声明顺序传递所有实参,不可乱序、缺参。
-
传参方式 :默认值传递,形参是实参的拷贝,基础类型修改不影响原数据。
-
引用类型特殊点:实参为指针、切片、map、函数、通道等引用类型时,函数内可通过间接引用修改原实参数据。
二、递归函数(5.2)
Go函数支持递归,即函数可以直接或间接调用自身。
核心使用场景:处理层级遍历、分治算法、递归遍历目录/数据结构等场景。
三、函数多返回值(5.3)
3.1 核心特性
-
Go支持函数返回多个返回值,是Go核心特性之一。
-
标准库通用规范:通常返回「结果值 + 错误信息」两个返回值。
3.2 嵌套调用规则
-
函数内部可将多返回值函数的调用直接作为当前函数的返回值。
-
调用多参函数时,可将多返回值函数调用作为其参数传入。
3.3 命名返回值规则
-
规范建议:为返回值定义精准变量名,提升代码可读性,明确返回值含义。
-
语法特性:若函数所有返回值均显式命名 ,函数内
return可省略操作数(裸返回)。 -
使用原则:无需为所有返回值强行命名,按需定义即可。
四、Go错误处理规范(5.4)
4.1 函数运行成功率分类
-
绝对成功函数 :几乎不会运行失败,仅极端灾难场景(内存溢出)出错,如
strings.Contains、strconv.FormatBool。 -
条件成功函数 :参数合法则运行成功,参数异常则失败,如
time.Date(时区为nil时失败)。 -
常规风险函数:绝大多数函数,错误不可控(I/O、网络、文件操作等),必须处理错误。
4.2 错误返回规范
-
Go将运行失败视为预期结果之一,而非异常崩溃。
-
单种失败原因:末尾返回布尔类型(常用变量名
ok)。 -
多种失败原因(主流):末尾返回
error类型,存储详细错误信息。
4.3 错误信息编写规范
-
错误信息避免大写、换行符(适配错误链式拼接场景)。
-
描述详尽精准,清晰说明问题细节,便于定位BUG。
五、函数值(一等公民)(5.5)
5.1 核心特性
Go中函数是第一类值,和普通变量地位平等:
-
拥有独立类型;
-
可赋值给变量、可作为函数参数、可作为函数返回值;
-
函数值调用方式与普通函数一致。
5.2 特殊限制
-
函数类型零值为
nil,调用nil函数值会触发 panic。 -
函数值不可比较,不能作为map的key。
六、匿名函数与闭包(5.6)
6.1 匿名函数定义
-
普通命名函数仅能在包级代码块声明。
-
匿名函数(函数字面量):无函数名的函数表达式,可在任意代码表达式中定义使用。
-
语法:去掉函数名的函数声明格式,可随用随定义。
6.2 闭包核心原理
-
匿名函数可访问外层函数的完整词法环境,引用外层局部变量。
-
函数值不仅存储代码逻辑,还会绑定变量状态。
-
Go的函数值本质就是闭包,这也是函数值为引用类型、不可比较的根本原因。
6.3 匿名函数递归规则
匿名函数无法直接递归调用,必须分两步:
-
先声明一个函数类型变量;
-
再将匿名函数赋值给该变量,通过变量实现递归调用。
七、可变参数函数(5.7)
7.1 语法规则
在参数列表最后一个参数 的类型前添加 ...,即为可变参数函数。
作用:接收任意数量的该类型参数。
7.2 核心限制
可变参数必须是参数列表的最后一位参数,否则编译报错。
八、Deferred延迟函数(5.8)
8.1 执行机制
-
语法:普通函数调用前加
defer关键字。 -
执行时机:
defer语句执行时,会立即计算函数参数,但延迟到当前函数结束前执行(无论函数是return正常结束,还是panic异常结束)。 -
执行顺序:多个defer语句,后进先出(逆序执行),声明越晚,执行越早。
8.2 核心使用场景
-
资源释放:文件关闭、连接断开、锁释放等成对操作,保证任意代码路径都能释放资源。
-
日志调试:记录函数进入、退出信息。
8.3 最佳实践
资源申请后立即编写defer释放语句,避免遗漏资源释放。
九、Panic运行时异常(5.9)
9.1 触发场景
-
运行时错误:数组越界、空指针引用、切片越界等,由Go运行时自动触发。
-
主动触发:手动调用内置
panic(任意值)函数。
9.2 执行流程
-
panic触发,当前goroutine暂停正常逻辑;
-
依次执行当前goroutine所有延迟的defer函数;
-
程序崩溃,输出panic值 + 函数调用堆栈信息。
9.3 使用规范
panic用于严重、不可恢复的程序内部逻辑错误,不可用于常规业务错误处理(常规错误用error返回)。
十、Recover异常捕获恢复(5.10)
10.1 核心作用
在defer函数内部 调用 recover(),可捕获当前panic,让程序从崩溃中恢复:
-
返回panic的错误值;
-
触发panic的函数终止运行,但可以正常返回,不导致程序整体崩溃;
-
无panic时调用recover,返回
nil。
10.2 核心使用规范(重点)
-
禁止全局捕获所有panic:panic后程序变量状态不可控,盲目恢复会引发未知BUG。
-
不恢复其他包的panic:公共API必须通过error返回业务错误,禁止抛出panic给调用方。
-
选择性恢复:仅恢复可预期、可修复的panic,尽量减少recover使用场景。
十一、本章核心总结(复习重点)
-
函数签名仅由参数、返回值类型决定,与变量名无关;
-
参数默认值传递,引用类型可修改原数据;
-
多返回值+error是Go标准错误处理范式;
-
函数是一等公民,匿名函数+闭包可绑定变量状态;
-
defer逆序执行,核心用于资源释放;
-
panic处理严重逻辑错误,recover选择性捕获,禁止滥用。