MST
星途 面试题库

面试题:Go函数模块化中错误处理与模块解耦

在Go函数模块化设计里,不同模块的函数可能会产生各种错误。假设你正在开发一个文件读取与数据解析的模块化程序,文件读取模块函数可能返回文件不存在、权限不足等错误,数据解析模块函数可能返回数据格式错误等。如何设计错误处理机制,既能有效传递和处理错误,又能保持模块之间的低耦合性?请给出具体的代码示例和解释。
38.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

代码示例

package main

import (
    "fmt"
    "os"
)

// 定义文件读取错误类型
type FileReadError struct {
    ErrMsg string
}

func (e *FileReadError) Error() string {
    return e.ErrMsg
}

// 定义数据解析错误类型
type DataParseError struct {
    ErrMsg string
}

func (e *DataParseError) Error() string {
    return e.ErrMsg
}

// 文件读取模块函数
func readFile(filePath string) ([]byte, error) {
    data, err := os.ReadFile(filePath)
    if err != nil {
        if os.IsNotExist(err) {
            return nil, &FileReadError{ErrMsg: "文件不存在"}
        }
        if os.IsPermission(err) {
            return nil, &FileReadError{ErrMsg: "权限不足"}
        }
        return nil, err
    }
    return data, nil
}

// 数据解析模块函数
func parseData(data []byte) (string, error) {
    // 这里简单示例,假设数据解析失败条件
    if len(data) == 0 {
        return "", &DataParseError{ErrMsg: "数据格式错误"}
    }
    return string(data), nil
}

// 主函数
func main() {
    filePath := "test.txt"
    data, err := readFile(filePath)
    if err != nil {
        if fileErr, ok := err.(*FileReadError); ok {
            fmt.Printf("文件读取错误: %v\n", fileErr.Error())
        } else {
            fmt.Printf("其他文件读取错误: %v\n", err)
        }
        return
    }
    result, err := parseData(data)
    if err != nil {
        if parseErr, ok := err.(*DataParseError); ok {
            fmt.Printf("数据解析错误: %v\n", parseErr.Error())
        } else {
            fmt.Printf("其他数据解析错误: %v\n", err)
        }
        return
    }
    fmt.Printf("解析结果: %s\n", result)
}

解释

  1. 定义错误类型
    • 为文件读取和数据解析分别定义了FileReadErrorDataParseError结构体类型,并实现error接口。这样不同模块的错误类型清晰,有利于模块间解耦。
  2. 文件读取模块函数
    • readFile函数负责读取文件,使用os.ReadFile进行文件读取。如果发生错误,根据错误类型判断是文件不存在还是权限不足,返回对应的自定义错误。其他未知错误直接返回。
  3. 数据解析模块函数
    • parseData函数负责数据解析,简单示例中如果数据长度为0则返回数据格式错误的自定义错误。
  4. 主函数
    • 在主函数中依次调用文件读取和数据解析函数。如果发生错误,使用类型断言判断错误类型,根据不同类型的错误进行相应处理,既能有效传递和处理错误,又保持了模块之间的低耦合性。不同模块只需关心自己的错误类型,而不需要了解其他模块内部的错误实现细节。