PHP转GO Day4 错误处理机制(计算器除零保护) 详细实现指南与问题解决方案

embedded/2025/3/31 21:56:10/

Day4 错误处理机制(计算器除零保护) 详细实现指南与问题解决方案, 包含代码对比和常见错误排查:


计算器除零错误处理指南


一、错误处理前代码(Day2版本)
case "/":fmt.Printf("结果:%.2f\n", a/b) // 危险!未处理除零

二、错误处理实现步骤


步骤1:添加除零检测
case "/":if b == 0 {fmt.Println("错误:除数不能为零")os.Exit(3) // 设置非零退出码}fmt.Printf("结果:%.2f\n", a/b)

步骤2:增强浮点零判断
// 更精确的浮点零判断(考虑舍入误差)
if math.Abs(b) < 1e-9 { // 当b的绝对值小于10^-9视为零fmt.Println("错误:除数过小可能导致计算异常")os.Exit(3)
}

步骤3:错误处理优化版
func divide(a, b float64) (float64, error) {if math.Abs(b) < 1e-9 {return 0, fmt.Errorf("除零错误:除数 %.2f 无效", b)}return a / b, nil
}// 在switch中调用:
case "/":result, err := divide(a, b)if err != nil {fmt.Println(err)os.Exit(3)}fmt.Printf("结果:%.2f\n", result)

三、PHP开发者特别注意

错误处理方式PHP实现Go实现关键差异
异常抛出throw new Exception()return 0, errors.New("msg")Go没有try/catch语法
错误捕获try { ... } catch () { }if err != nil { ... }必须显式检查错误
错误类型继承Exception类实现error接口Go错误是普通值

四、典型问题与解决方案


问题1:浮点零判断失效

🛑 现象
输入calc 5 / 0.0000000001未触发错误
🔍 原因分析
直接使用b == 0判断不适用于浮点数
✅ 解决方案
改用阈值判断:

import "math"if math.Abs(b) < 1e-9 { // 调整阈值根据精度需求// 触发错误
}

问题2:错误信息重复

🛑 现象
同时显示默认错误和自定义错误
🔍 原因分析
未及时退出程序导致继续执行
✅ 解决方案
添加returnos.Exit

if err != nil {fmt.Println(err)os.Exit(3) // 确保退出return     // 双重保障
}

问题3:退出码冲突

🛑 现象
多个错误使用相同退出码
🔍 原因分析
未区分错误类型
✅ 解决方案
定义错误码常量:

const (ExitCodeOK = iota // 0ExitInvalidArgs   // 1ExitNumberFormat  // 2ExitDivideZero    // 3ExitUnknownOp     // 4
)

五、完整增强版代码

package mainimport ("fmt""math""os""strconv"
)const ExitDivideZero = 3 // 专用退出码func divide(a, b float64) (float64, error) {if math.Abs(b) < 1e-9 {return 0, fmt.Errorf("数学错误:除数 %.12f 无效", b)}return a / b, nil
}func main() {if len(os.Args) < 4 {fmt.Println("用法:calc 数字1 运算符(+ - * /) 数字2")os.Exit(1)}a, err := strconv.ParseFloat(os.Args[1], 64)if err != nil {fmt.Printf("输入错误:%s 不是有效数字\n", os.Args[1])os.Exit(2)}op := os.Args[2]b, err := strconv.ParseFloat(os.Args[3], 64)if err != nil {fmt.Printf("输入错误:%s 不是有效数字\n", os.Args[3])os.Exit(2)}var result float64switch op {case "+":result = a + bcase "-":result = a - bcase "*":result = a * bcase "/":result, err = divide(a, b)if err != nil {fmt.Println(err)os.Exit(ExitDivideZero)}default:fmt.Printf("运算符错误:不支持 '%s'\n", op)os.Exit(4)}fmt.Printf("结果:%.4f\n", result) // 统一保留4位小数
}

六、测试用例与预期

测试命令预期结果验证要点
calc 10 / 0错误:除数 0.000000 无效整数零检测
calc 5 / 0.0000001正常输出结果有效小除数
calc 8 / 0.0000000000001数学错误:除数 0.000000无效科学计数法处理
calc 7 / abc输入错误:abc 不是有效数字错误处理优先级

七、调试技巧

  1. 打印变量值
    fmt.Printf("[DEBUG] a=%.2f, b=%.2f\n", a, b)
    
  2. 使用Delve调试器
    dlv debug main.go -- 10 / 0
    (dlv) break main.divide
    (dlv) continue
    
  3. 查看退出码
    ./calc 10 / 0
    echo $? # 显示3(ExitDivideZero)
    

通过本指南,可系统性地为计算器添加健壮的除零保护机制。建议在VS Code中设置断点逐步调试,观察错误处理流程的执行路径。


http://www.ppmy.cn/embedded/177518.html

相关文章

单片机内存划分总览与介绍

1 单片机内存划分总览 内存区域 存储内容 特性 FLASH (Text) 代码&#xff08;.text&#xff09;、常量&#xff08;.rodata&#xff09; 只读&#xff0c;掉电不丢失 RAM .data&#xff08;已初始化全局变量&#xff09; 读写&#xff0c;掉电丢失 .bss&#xff08…

K8S学习之基础四十六:k8s中部署Kibana

部署kibana组件 上传kibina镜像到harbor 部署kibana组件&#xff0c;包括svc和deplomentvi kibana.yaml apiVersion: v1 kind: Service metadata:name: kibananamespace: kube-logginglabels:app: kibana spec:ports:- port: 5601selector:app: kibana --- apiVersion: apps/…

STM32__红外避障模块的使用

目录 一、红外避障模块 概述 二、直接读取OUT引脚电平 三、使用中断方式触发 一、红外避障模块 概述 引脚解释&#xff1a; VCC接3.3V 或 5.0VGND接开发板的GNDOUT数字量输出(0或1&#xff09;; 低电平时表示前方有障碍 ; 通过可调电阻调整检测距离 产品特点&#xff1a; …

Kubernetes 中导致 pod 重启的原因

原因 在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;导致 Pod 重启的原因主要有以下几种&#xff1a; 1. 应用程序异常 应用进程崩溃&#xff1a;Pod 内部的应用程序由于未处理的异常、内存溢出&#xff08;OOM&#xff09;、访问非法地址等原因崩溃&#xff0c;导…

2025最新-智慧小区物业管理系统

目录 1. 项目概述 2. 技术栈 3. 功能模块 3.1 管理员端 3.1.1 核心业务处理模块 3.1.2 基础信息模块 3.1.3 数据统计分析模块 3.2 业主端 5. 系统架构 5.1 前端架构 5.2 后端架构 5.3 数据交互流程 6. 部署说明 6.1 环境要求 6.2 部署步骤 7. 使用说明 7.1 管…

STM32八股【1】-----启动流程和startup文件理解

启动流程 知识点 MCU 上电复位。MSP从向量表第0个地址读取一个32位&#xff08;2字节&#xff09;的值并保存&#xff0c;该值为栈顶地址。PC计数器从第1个地址读取一个两字节的值并保存&#xff0c;该值为程序入口&#xff0c;一般是Reset_Handler。想了解FLASH地址映射可以…

QOpenGLWidget视频画面上绘制矩形框

一、QPainter绘制 在QOpenGLWidget中可以绘制&#xff0c;并且和OpenGL的内容叠在一起。paintGL里面绘制完视频后&#xff0c;解锁资源&#xff0c;再用QPainter绘制矩形框。这种方式灵活性最好。 void VideoGLWidget::paintGL() {glClear(GL_COLOR_BUFFER_BIT);m_program.bi…

基于springboot人脸识别的社区流调系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;社区流调系统当然不能排除在外。社区流调系统是在实际应用和软件工程的开发原理之上&#xff0c;运用Java语言、Spring Boot框架、人脸校对…