第5章:Go语言错误处理和异常

news2025/1/12 0:15:55

第5章:Go语言错误处理和异常

5.1 错误类型基础

5.1.1 error接口

// error接口定义
type error interface {
    Error() string
}

// 自定义错误
type CustomError struct {
    Message string
    Code    int
}

func (e *CustomError) Error() string {
    return fmt.Sprintf("错误码: %d, 信息: %s", e.Code, e.Message)
}

5.1.2 创建和使用错误

// 创建简单错误
func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("除数不能为零")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("发生错误:", err)
        // 处理错误
    }
}

5.2 错误处理模式

5.2.1 多返回值错误处理

func readFile(filename string) ([]byte, error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        // 错误处理
        return nil, fmt.Errorf("读取文件失败: %v", err)
    }
    return data, nil
}

func processFile(filename string) {
    data, err := readFile(filename)
    switch {
    case err == nil:
        // 正常处理
        fmt.Println(string(data))
    case os.IsNotExist(err):
        fmt.Println("文件不存在")
    case os.IsPermission(err):
        fmt.Println("权限不足")
    default:
        fmt.Println("未知错误:", err)
    }
}

5.2.2 错误类型断言

type ValidationError struct {
    Field string
    Value interface{}
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("验证错误:字段 %s 值 %v 不合法", e.Field, e.Value)
}

func validateAge(age int) error {
    if age < 0 || age > 150 {
        return &ValidationError{
            Field: "Age",
            Value: age,
        }
    }
    return nil
}

func main() {
    err := validateAge(-5)
    if err != nil {
        if ve, ok := err.(*ValidationError); ok {
            fmt.Printf("特定错误处理:%s\n", ve.Error())
        }
    }
}

5.3 panic和recover

5.3.1 panic触发

func riskyOperation() {
    panic("发生严重错误")
}

func main() {
    riskyOperation()  // 程序将立即终止
}

5.3.2 recover捕获异常

func recoverExample() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获到panic:", r)
            // 可以进行日志记录、资源清理等
        }
    }()

    // 模拟可能发生panic的代码
    panic("unexpected error")
}

func main() {
    recoverExample()
    fmt.Println("程序继续执行")
}

5.4 自定义错误处理

5.4.1 错误包装

func wrapError(err error) error {
    return fmt.Errorf("操作失败:%w", err)
}

func complexOperation() error {
    // 模拟底层错误
    baseErr := errors.New("数据库连接失败")
    return wrapError(baseErr)
}

func main() {
    err := complexOperation()
    
    // 错误解包
    if errors.Is(err, baseErr) {
        fmt.Println("匹配到原始错误")
    }
}

5.4.2 错误日志记录

type Logger struct {
    file *os.File
}

func (l *Logger) LogError(err error) {
    if err != nil {
        logEntry := fmt.Sprintf("%s - Error: %v\n", 
            time.Now().Format(time.RFC3339), err)
        l.file.WriteString(logEntry)
    }
}

func main() {
    logger, _ := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    defer logger.Close()

    customLogger := &Logger{file: logger}
    
    err := someRiskyOperation()
    customLogger.LogError(err)
}

5.5 最佳实践

5.5.1 错误处理原则

  1. 始终检查错误
  2. 只处理可以处理的错误
  3. 在合适的抽象层级传播错误
  4. 避免忽略错误
  5. 使用错误包装增加上下文信息

5.5.2 常见错误处理模式

// 错误处理模式示例
func processData(data []byte) error {
    if len(data) == 0 {
        return errors.New("数据为空")
    }

    // 处理数据的复杂逻辑
    return nil
}

func main() {
    data := []byte{}
    if err := processData(data); err != nil {
        log.Printf("处理失败:%v", err)
        // 根据不同错误类型采取不同处理策略
        return
    }
}

实践项目:简单的配置文件解析器

type Config struct {
    Database struct {
        Host string
        Port int
    }
}

func parseConfig(filename string) (*Config, error) {
    data, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, fmt.Errorf("读取配置文件失败: %w", err)
    }

    var config Config
    if err := json.Unmarshal(data, &config); err != nil {
        return nil, fmt.Errorf("解析配置文件失败: %w", err)
    }

    return &config, nil
}

func main() {
    config, err := parseConfig("config.json")
    if err != nil {
        switch {
        case os.IsNotExist(err):
            log.Fatal("配置文件不存在")
        case os.IsPermission(err):
            log.Fatal("无权限读取配置文件")
        default:
            log.Fatalf("配置解析错误: %v", err)
        }
    }

    fmt.Printf("数据库配置:%+v\n", config.Database)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2275192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring——自动装配

假设一个场景&#xff1a; 一个人&#xff08;Person&#xff09;有一条狗&#xff08;Dog&#xff09;和一只猫(Cat)&#xff0c;狗和猫都会叫&#xff0c;狗叫是“汪汪”&#xff0c;猫叫是“喵喵”&#xff0c;同时人还有一个自己的名字。 将上述场景 抽象出三个实体类&…

计算机网络(三)——局域网和广域网

一、局域网 特点&#xff1a;覆盖较小的地理范围&#xff1b;具有较低的时延和误码率&#xff1b;使用双绞线、同轴电缆、光纤传输&#xff0c;传输效率高&#xff1b;局域网内各节点之间采用以帧为单位的数据传输&#xff1b;支持单播、广播和多播&#xff08;单播指点对点通信…

错误的类文件: *** 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中

一、问题 用maven对一个开源项目打包时&#xff0c;遇到了“错误的类文件: *** 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中。”&#xff1a; 二、原因 原因是当前java环境是Java 8&#xff08;版本52.0&#xff09;&#xff0c;但…

【大模型入门指南 07】量化技术浅析

【大模型入门指南】系列文章&#xff1a; 【大模型入门指南 01】深度学习入门【大模型入门指南 02】LLM大模型基础知识【大模型入门指南 03】提示词工程【大模型入门指南 04】Transformer结构【大模型入门指南 05】LLM技术选型【大模型入门指南 06】LLM数据预处理【大模型入门…

在线工具箱源码优化版

在线工具箱 前言效果图部分源码源码下载部署教程下期更新 前言 来自缤纷彩虹天地优化后的我爱工具网源码&#xff0c;百度基本全站收录&#xff0c;更能基本都比较全&#xff0c;个人使用或是建站都不错&#xff0c;挑过很多工具箱&#xff0c;这个比较简洁&#xff0c;非常实…

@LocalBuilder装饰器: 维持组件父子关系

一、前言 当开发者使用Builder做引用数据传递时&#xff0c;会考虑组件的父子关系&#xff0c;使用了bind(this)之后&#xff0c;组件的父子关系和状态管理的父子关系并不一致。为了解决组件的父子关系和状态管理的父子关系保持一致的问题&#xff0c;引入LocalBuilder装饰器。…

C 语言内存探秘:数据存储的字节密码

文章目录 一、数据在内存中的存储1、基本数据类型存储2、数组存储3、结构体存储1、基本存储规则2、举例说明3、查看结构体大小和成员偏移量的方法 二、大小端字节序三、字节序的判断 一、数据在内存中的存储 1、基本数据类型存储 整型&#xff1a;如int类型&#xff0c;通常在…

双因素身份验证技术在NPI区域邮件安全管控上的解决思路

在制造业中&#xff0c;NPI&#xff08;New Product Introduction&#xff0c;新产品导入&#xff09;区域是指专门负责新产品从概念到市场推出全过程的部门或团队。NPI 的目标是确保新产品能够高效、高质量地投入生产&#xff0c;并顺利满足市场需求。在支撑企业持续创新和竞争…

浙江安吉成新的分布式光伏发电项目应用

摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活的布局、更低的建设成本和更高…

更新Office后,LabVIEW 可执行程序生成失败

问题描述&#xff1a; 在计算机中&#xff0c;LabVIEW 开发的源程序运行正常&#xff0c;但在生成可执行程序时提示以下错误&#xff1a; ​ A VI broke during the build process from being saved without a block diagram. Either open the build specification to include…

mysql-operator容器化部署mysql8

基础组件容器化 前一段时间容器化了容器的s3和pika。由于已经有开源方案&#xff0c;本次mysql直接以operator容器化。使用的是[presslabs的mysql-operator]https://github.com/presslabs/mysql-operator。 主要特征 presslabs/mysql-operator自动化搭建主从集群。使用XtraBack…

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理 1.uni.getSystemInfoSync().screenWidth; 获取屏幕宽度 2.uni.onWindowResize&#xff08;&#xff09; 实时监测屏幕宽度变化 3.根据宽度的大小拿到每行要展示的数量itemsPerRow 4.为了确保样式能够根据 items…

[OPEN SQL] 限定选择行数

本次操作使用的数据库表为SCUSTOM&#xff0c;其字段内容如下所示 航班用户(SCUSTOM) 该数据库表中的部分值如下所示 指定查询多少行数据&#xff0c;我们可以使用语法UP TO n ROWS来实现对数据前n项的查询 语法格式 SELECT * FROM <dbtab> UP TO n ROWS 参数说明 db…

金融项目实战 02|接口测试分析、设计以及实现

目录 ⼀、接口相关理论 二、接口测试 1、待测接口&#xff1a;投资业务 2、接口测试流程 3、设计用例理论 1️⃣设计方法 2️⃣工具 4、测试点提取 5、测试用例&#xff08;只涉及了必测的&#xff09; 1️⃣注册图⽚验证码、注册短信验证码 2️⃣注册 3️⃣登录 …

74 mysql having 的实现

前言 这里 我们主要是 看一下 having 的相关实现 having 经常是配合 group by 这边进行使用, 进行一个基于 group by 之后的结果的一个, 条件限定 我们这里 以最简单的 group by having 来进行调试, 他会分为 两个阶段, 一个阶段是 group by 之后的结果输出到临时表, 另外…

Google发布图像生成新工具Whisk:无需复杂提示词,使用图像和人工智能将想法可视化并重新混合

Whisk 是 Google Labs 的一项新实验&#xff0c;可使用图像进行快速而有趣的创作过程。Whisk不会生成带有长篇详细文本提示的图像&#xff0c;而是使用图像进行提示。只需拖入图像&#xff0c;即可开始创建。 whisk总结如下&#xff1a; Whisk 是 Google 实验室最新的生成图像实…

K8s Pod OOMKilled,监控却显示内存资源并未打满

1. 问题现象 pod一直重启&#xff0c;通过grafana查看&#xff0c;发现内存使用率并没有100%。 2. 排查过程 2.1 describe查看pod最新一次的状态 可以明显看到&#xff0c;最近一次的重启就是因为内存不足导致的。 2.2 describe 查看node节点状态 找到原因了&#xff0c;原来…

33.3K 的Freqtrade:开启加密货币自动化交易之旅

“ 如何更高效、智能地进行交易成为众多投资者关注的焦点。” Freqtrade 是一款用 Python 编写的免费开源加密货币交易机器人。它就像一位不知疲倦的智能交易助手&#xff0c;能够连接到众多主流加密货币交易所&#xff0c;如 Binance、Bitmart、Bybit 等&#xff08;支…

vscode开启调试模式,结合Delve调试器调试golang项目详细步骤

1.前期准备 (1).在vs code中的扩展程序中搜索并安装Go扩展程序 (2).安装 Delve 调试器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打开vs code的命令面板&#xff0c;输入Go: Install/Update Tools&#xff0c;并单击该命令执行&#xff0c;安装或更新Go语…

Postman接口测试03|执行接口测试、全局变量和环境变量、接口关联、动态参数、断言

目录 七、Postman 1、安装 2、postman的界面介绍 八、Postman执行接口测试 1、请求页签 3、响应页签 九、Postman的环境变量和全局变量 1、创建环境变量和全局变量可以解决的问题 2、postman中的操作-全局变量 1️⃣手动设置 2️⃣代码设置 3️⃣界面获取 4️⃣代…