DevCN
菜单
全部文章快讯开发深度热点

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分钟”。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。