Go 函数与多返回值:平均值计算中的空输入处理
把计算从main中拆出来,用两个返回值区分“合法平均值为0”和“没有可计算的数据”。理解局部变量如何隔离函数内部细节。
本节目标
把计算从main中拆出来,用两个返回值区分“合法平均值为0”和“没有可计算的数据”。理解局部变量如何隔离函数内部细节。
前置知识
理解变量、循环和条件判断;能够阅读[]int形式的整数列表。
准备与运行
在一个新的练习目录执行以下命令。目录名可以修改;若该目录已经初始化过模块,不要重复执行go mod init。
mkdir go-lesson-04
cd go-lesson-04
go mod init example.com/devcn/lesson04将下方完整代码保存为当前目录的main.go,然后执行:
go fmt ./...
go run .先用go version确认工具链可用。本例在Go 1.25.7、macOS ARM64环境验证,只使用标准库;没有测试所有操作系统和Go版本。
核心概念
函数把一段有明确输入输出的逻辑命名。本例average接收整数切片,返回float64和bool:第一个是平均值,第二个说明结果是否有效。调用者应先检查有效性,再决定如何展示数值。
这种设计比单独返回0更明确,因为[]int{0,0}的平均值确实是0,而空列表没有平均值,两者不应混淆。也可以设计为返回error,但本例只有“有数据/没数据”两种状态,布尔值足够表达。
total在函数内部声明,外部不能直接访问它。它只负责一次调用的累加。函数被多次调用时,每次都会重新初始化total,结果不会自动累计到上次的值中。
完整示例
package main
import "fmt"
func average(values []int) (float64, bool) {
if len(values) == 0 {
return 0, false
}
total := 0
for _, v := range values {
total += v
}
return float64(total) / float64(len(values)), true
}
func main() {
v, ok := average([]int{10, 20, 30})
fmt.Println(v, ok)
_, ok = average(nil)
fmt.Println(ok)
}运行后应得到:
20 true
false代码如何工作
进入函数先检查长度。空输入立即返回0和false,避免后面出现零分母。非空时,循环累加每个元素,再把总和与元素个数转为浮点数进行除法。
main第一次传入10、20、30,得到20和true。第二次用nil切片验证空输入规则,得到false;这里主动忽略了无效数值,体现出“标记无效时不使用结果”的约定。
这个函数没有修改输入切片,因此同一组数据可以用于多次计算。它也没有负责打印,让计算逻辑可以在命令行、网页或测试中复用。
常见错误与边界
- 不检查有效标记,会把空输入错误显示为平均值0。
- 用整数除法计算平均值可能丢掉小数,应在除法前转换。
- 本例用int累加,超大数值可能溢出;面向计费或精确统计时,应按数据范围重新选择表示方式。
- 数学上可以计算负数的平均值,但学习分钟数等业务场景应在调用前校验是否允许负数。
练习
分别计算[]int{0,0}、nil和[]int{1,2},比较数值与有效标记。
参考答案
结果依次为0与true、0与false、1.5与true。main中可临时使用:
for _, values := range [][]int{{0, 0}, nil, {1, 2}} {
value, ok := average(values)
fmt.Println(value, ok)
}空输入返回的0只是占位结果。页面显示时,ok为false更适合显示“暂无记录”,而不是“平均0分钟”。
文章回复
0 条公开回复