网站目录权限,外贸订单,wordpress 免费 模板下载,google框架三件套错误的分类
在 Go 语言中#xff0c;错误是通过实现 error 接口的类型表示的#xff0c;但不同场景下的错误可以按性质和用途进行分类。以下是 Go 语言错误的常见分类#xff0c;以及每类错误的解释和示例#xff1a; 标准错误类型
标准库中定义了许多常见的错误类型错误是通过实现 error 接口的类型表示的但不同场景下的错误可以按性质和用途进行分类。以下是 Go 语言错误的常见分类以及每类错误的解释和示例 标准错误类型
标准库中定义了许多常见的错误类型用于表示各种常见的错误场景。以下是一些 Go 标准库中常见的错误类型和相关包
errors.New 和 fmt.Errorf 用于创建自定义的错误。 标准库提供的最基础的错误类型。
示例
import ( errors fmt
) err1 : errors.New(this is an error)
err2 : fmt.Errorf(formatted error: %d, 42) IO 相关错误
io 包 包含基础 I/O 操作的错误类型。
常见错误 io.EOF表示流结束End Of File。 io.ErrUnexpectedEOF在读取流时遇到意外的 EOF。 io.ErrClosedPipe操作已关闭的管道。
示例
import io
if err io.EOF { fmt.Println(Reached end of file)
} 文件操作相关错误
os 包 处理文件系统相关的错误。
常见错误 os.ErrNotExist文件或目录不存在。 os.ErrExist文件或目录已经存在。 os.ErrPermission权限不足。 os.ErrInvalid无效操作。
示例
import os if errors.Is(err, os.ErrNotExist) {fmt.Println(File does not exist)
} 网络相关错误
net 包 网络操作相关的错误。
常见错误 net.InvalidAddrError无效地址错误。 net.UnknownNetworkError未知网络类型错误。 net.AddrError地址解析错误。 net.DNSError域名解析错误。
示例
import net_, err : net.LookupHost(invalid_domain)
if dnsErr, ok : err.(*net.DNSError); ok {fmt.Println(DNS error:, dnsErr)
} JSON 相关错误
encoding/json 包 JSON 编码和解码的错误。
常见错误 json.InvalidUnmarshalError解码到无效的目标。 json.UnmarshalTypeErrorJSON 与目标类型不匹配。
示例
import encoding/json var data interface{}
err : json.Unmarshal([]byte(invalid json), data) if syntaxErr, ok : err.(*json.SyntaxError); ok { fmt.Println(JSON Syntax Error at offset:, syntaxErr.Offset)
} HTTP 相关错误
net/http 包 HTTP 请求与响应相关的错误。
常见错误 http.ErrHandlerTimeoutHTTP 处理程序超时。 http.ErrBodyNotAllowedHTTP 请求体不被允许。
示例
import net/http if errors.Is(err, http.ErrHandlerTimeout) { fmt.Println(HTTP handler timeout)
} 时间解析相关错误
time 包 处理时间解析或格式化错误。
常见错误 time.ErrBad时间字符串格式错误。
示例
import time_, err : time.Parse(2006-01-02, invalid-date)
if err ! nil { fmt.Println(Time parsing error:, err)
} 数据库相关错误
database/sql 包 数据库操作相关的错误。
常见错误 sql.ErrNoRows查询未返回结果。 sql.ErrTxDone事务已完成不能再执行操作。
示例
import database/sql if errors.Is(err, sql.ErrNoRows) { fmt.Println(No rows found)
} 压缩解压相关错误
compress/gzip 包 用于处理 gzip 格式的错误。
常见错误 gzip.ErrHeadergzip 文件头错误。 加密解密相关错误
crypto 和 crypto/x509 包 加密或证书解析相关错误。
常见错误 x509.IncorrectPasswordError密码错误。 x509.UnknownAuthorityError未知的证书颁发机构。 按错误来源分类
应用级错误
应用程序逻辑中定义的错误如输入验证失败、业务规则不满足等。这些错误通常由程序员明确定义。
示例
type ValidationError struct { Field string Msg string
} func (e ValidationError) Error() string { return fmt.Sprintf(validation failed on field %s: %s, e.Field, e.Msg)
}
系统级错误
系统资源相关的错误包括文件访问、网络问题等。 示例
func readConfig(filename string) error { _, err : os.ReadFile(filename) if err ! nil {return fmt.Errorf(failed to read config: %w, err) } return nil
}
第三方库错误
使用第三方库时返回的错误需要通过文档或代码了解这些错误的含义并采取适当措施。 示例
func sendMessageToKafka() error { err : producer.SendMessage(message) if err ! nil { return fmt.Errorf(kafka producer error: %w, err) } return nil
} 按错误处理方式分类
可恢复错误
可以通过重新尝试或特定逻辑处理恢复的错误。 示例
func retryOperation(attempts int) error { for i : 0; i attempts; i {err : doSomething() if err nil { return nil } time.Sleep(1 * time.Second) // 等待后重试 } return fmt.Errorf(operation failed after %d attempts, attempts)
}
不可恢复错误
表示程序的逻辑或系统的严重错误无法通过重新尝试解决如非法状态、编程错误等。
示例
func mustDivide(a, b int) int { if b 0 { panic(division by zero) } return a / b
} 按错误语义分类
用户输入错误
用户提供的输入不满足预期导致的错误。
示例
func validateInput(input string) error { if input {return fmt.Errorf(input cannot be empty) } return nil
}
数据处理错误
数据格式、解析、转换等问题。
示例
func parseInt(value string) (int, error) { num, err : strconv.Atoi(value) if err ! nil { return 0, fmt.Errorf(failed to parse integer: %w, err) } return num, nil
}
网络/IO 错误
网络连接失败、超时、文件系统操作失败等问题。
示例
func fetchData(url string) ([]byte, error) { resp, err : http.Get(url) if err ! nil { return nil, fmt.Errorf(failed to fetch data: %w, err) } defer resp.Body.Close() return io.ReadAll(resp.Body) }
业务逻辑错误
业务逻辑不满足需求导致的错误。
示例
func checkAccountBalance(balance, withdrawAmount float64) error { if withdrawAmount balance { return fmt.Errorf(insufficient balance) } return nil
} 按错误表现分类
明确错误
明确的错误通过 error 接口表示并具有清晰的语义。
示例
return fmt.Errorf(unable to connect to database: %w, err)
模糊错误
返回的错误缺乏上下文信息不利于调试。
示例
return errors.New(something went wrong) // 不清楚具体问题是什么 总结
Go 中的错误分类可以帮助开发者更清晰地理解错误的来源和性质从而制定合理的处理策略。推荐 使用明确的错误上下文。 尽量细化错误类型尤其是应用级错误。 使用 errors.Is 和 errors.As 对错误进行分类处理。 在必要的场景下记录日志但不要重复记录错误信息。 错误处理规范
错误检查与优先处理 及时检查错误不要忽略返回的错误值。 优先处理错误如果发生错误尽快中止当前流程或采取修复措施。
好的示例
func readFile(filename string) ([]byte, error) { data, err : os.ReadFile(filename) if err ! nil { return nil, fmt.Errorf(failed to read file %s: %w, filename, err) } return data, nil
}
坏的示例
func readFile(filename string) ([]byte, error) { data, _ : os.ReadFile(filename) // 忽略错误可能导致不可预见的问题 return data, nil
} 使用错误包装提供上下文信息 使用 fmt.Errorf 和 %w 包装错误保留错误链路。 错误信息应清晰表明发生错误的上下文。
好的示例
func processFile(filename string) error { file, err : os.Open(filename) if err ! nil { return fmt.Errorf(failed to open file %s: %w, filename, err) } defer file.Close() // 文件处理逻辑... return nil
}
坏的示例
func processFile(filename string) error { _, err : os.Open(filename) if err ! nil { return err // 丢失了错误上下文难以追踪来源 } return nil
} 自定义错误类型 针对特定业务场景创建自定义错误类型以提供丰富的上下文。
好的示例
type ValidationError struct { Field string Message string
} func (e ValidationError) Error() string { return fmt.Sprintf(validation failed on field %s: %s, e.Field, e.Message)
} func validateInput(input string) error { if input { return ValidationError{input, cannot be empty} } return nil
}
坏的示例
func validateInput(input string) error { if input { return fmt.Errorf(invalid input) // 错误信息缺乏上下文 } return nil
} 使用 errors.Is 和 errors.As 检查错误 使用 errors.Is 检查错误是否是某种特定类型。 使用 errors.As 提取并处理特定的错误类型。
对比 特性errors.Iserrors.As用途检查错误值是否相等或包装目标错误检查错误是否为特定类型参数错误和目标错误值错误和目标错误类型的指针返回值布尔值布尔值目标指针可能会被赋值支持链式错误是是适用场景判断是否是某个特定错误判断是否属于某个特定类型的错误 好的示例
func handleError(err error) { if errors.Is(err, os.ErrNotExist) { fmt.Println(文件不存在) } var pathErr *os.PathError if errors.As(err, pathErr) { fmt.Printf(路径错误: %s\n, pathErr.Path) }
} 避免滥用 panic使用显式错误返回 panic 仅用于不可恢复的错误普通错误应返回 error。 提供有意义的错误信息。
好的示例
func divide(a, b int) (int, error) { if b 0 { return 0, fmt.Errorf(division by zero) } return a / b, nil
}
坏的示例
func divide(a, b int) int { if b 0 { panic(division by zero) // 滥用 panic不建议用于常规错误处理 } return a / b
} 日志与错误分离 错误和日志分层日志应由调用方处理库函数仅返回错误。 日志通常在服务层或调用者处理库函数不应记录日志。
好的示例
func fetchData(url string) ([]byte, error) { resp, err : http.Get(url) if err ! nil { return nil, fmt.Errorf(failed to fetch data from %s: %w, url, err) } defer resp.Body.Close() if resp.StatusCode ! http.StatusOK { return nil, fmt.Errorf(unexpected status code: %d, resp.StatusCode) } return io.ReadAll(resp.Body)
}
坏的示例
func fetchData(url string) ([]byte, error) { resp, err : http.Get(url) if err ! nil { log.Printf(error: %v, err) // 不必要的日志记录 return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body)
} 使用 defer 简化资源清理 使用 defer 保证资源在函数退出时被正确释放。
好的示例
func processLargeFile(filename string) error { file, err : os.Open(filename) if err ! nil { return fmt.Errorf(failed to open file: %w, err) } defer file.Close() // 确保资源释放 // 文件处理逻辑... return nil
}
坏的示例
func processLargeFile(filename string) error { file, err : os.Open(filename) if err ! nil { return err } // 如果忘记关闭文件会导致资源泄露 file.Close() return nil
} 分层处理错误 在业务逻辑层返回错误允许调用方决定是否记录日志。 在顶层捕获错误并进行统一处理。
好的实践
// 库函数
func queryDatabase(query string) ([]Record, error) { rows, err : db.Query(query) if err ! nil { return nil, fmt.Errorf(database query failed: %w, err) } defer rows.Close() // 解析数据... return records, nil
} // 应用层
func handleRequest(query string) { records, err : queryDatabase(query) if err ! nil { log.Printf(query error: %v, err) return } fmt.Println(records)
}
错误与日志处理的推荐实践
不同层级对错误和日志的处理
数据访问层DAL/Repository
职责直接与数据库或其他持久化存储交互。 错误处理 返回具体的、易于处理的错误。例如SQL 执行失败、数据未找到等。 尽量使用错误包装 (fmt.Errorf)为上层提供上下文。 不要记录日志交由上层决定是否需要记录。 示例
func GetUserByID(id int) (*User, error) { user : User{} err : db.QueryRow(SELECT * FROM users WHERE id ?, id).Scan(user.ID, user.Name) if errors.Is(err, sql.ErrNoRows) { return nil, fmt.Errorf(user with ID %d not found: %w, id, err) } if err ! nil { return nil, fmt.Errorf(failed to fetch user: %w, err) } return user, nil
} 服务层Service/Use Case
职责实现业务逻辑。 错误处理 捕获底层错误并添加业务语义上下文。 根据需要返回特定业务错误或通用错误。 可对一些关键错误进行日志记录如影响业务流程的错误。 日志记录 记录错误可能对调试或审计有价值的信息。 日志应包含业务上下文如用户 ID、请求参数等。 示例
func ProcessOrder(orderID int) error { order, err : repo.GetOrderByID(orderID) if err ! nil { return fmt.Errorf(failed to process order %d: %w, orderID, err) } if order.Status ! pending { return fmt.Errorf(order %d is not in a pending state, orderID) } // 业务逻辑... return nil
} 控制器层Controller/Handler
职责处理用户请求并返回响应。 错误处理 将服务层的错误转换为用户友好的消息HTTP 状态码或自定义响应。 不应暴露底层实现细节。 日志记录 在请求入口处记录重要的请求信息。 在错误返回时记录错误上下文和请求相关信息。 示例
func OrderHandler(w http.ResponseWriter, r *http.Request) { orderID, err : strconv.Atoi(r.URL.Query().Get(id)) if err ! nil { http.Error(w, invalid order ID, http.StatusBadRequest) return } err service.ProcessOrder(orderID) if err ! nil { log.Printf(failed to process order: %v, err) http.Error(w, failed to process order, http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK)
} 错误与日志的推荐实践
错误返回层级 底层如 DAL 返回详细的上下文错误方便上层理解问题。 不记录日志避免重复记录。 中间层如 Service 包装底层错误提供业务相关的上下文。 根据需要选择是否记录关键日志。 顶层如 Controller 转换错误为用户友好的消息。 记录完整的请求上下文和错误信息。 日志记录层级 入口点Controller/Handler 记录请求相关的信息URL、参数、用户身份等。 记录最终的响应状态。 服务层 记录对业务有重要影响的错误或状态变化。 数据层 尽量不记录日志避免暴露内部实现细节。 常见反模式与改进 重复记录日志 底层记录错误上层再次记录相同错误导致日志冗余。 改进仅在一个明确的层级记录日志。 暴露内部错误细节 直接将数据库错误返回到用户端。 改进在顶层捕获并转换为用户友好的消息。 忽略日志上下文 日志中缺乏关键信息如用户 ID、操作参数等。 改进在日志中包含足够的上下文信息。 总结
错误处理应遵循逐层封装的原则每一层专注于自身职责避免信息泄漏或日志冗余。日志记录应关注调试和审计价值并在错误信息中添加业务或操作上下文从而提高系统的可维护性和可观测性。 文章转载自: http://www.morning.yqkmd.cn.gov.cn.yqkmd.cn http://www.morning.rpgdd.cn.gov.cn.rpgdd.cn http://www.morning.dtcsp.cn.gov.cn.dtcsp.cn http://www.morning.tnqk.cn.gov.cn.tnqk.cn http://www.morning.hnkkm.cn.gov.cn.hnkkm.cn http://www.morning.mdmc.cn.gov.cn.mdmc.cn http://www.morning.pmmrb.cn.gov.cn.pmmrb.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.wrbnh.cn.gov.cn.wrbnh.cn http://www.morning.nrlsg.cn.gov.cn.nrlsg.cn http://www.morning.wkjzt.cn.gov.cn.wkjzt.cn http://www.morning.rydhq.cn.gov.cn.rydhq.cn http://www.morning.mxxsq.cn.gov.cn.mxxsq.cn http://www.morning.jmmz.cn.gov.cn.jmmz.cn http://www.morning.flxgx.cn.gov.cn.flxgx.cn http://www.morning.kybpj.cn.gov.cn.kybpj.cn http://www.morning.mlwpr.cn.gov.cn.mlwpr.cn http://www.morning.pbpcj.cn.gov.cn.pbpcj.cn http://www.morning.hgkbj.cn.gov.cn.hgkbj.cn http://www.morning.smrty.cn.gov.cn.smrty.cn http://www.morning.gxqpm.cn.gov.cn.gxqpm.cn http://www.morning.bkxnp.cn.gov.cn.bkxnp.cn http://www.morning.wftrs.cn.gov.cn.wftrs.cn http://www.morning.gydsg.cn.gov.cn.gydsg.cn http://www.morning.ntzbr.cn.gov.cn.ntzbr.cn http://www.morning.ttxnj.cn.gov.cn.ttxnj.cn http://www.morning.txmlg.cn.gov.cn.txmlg.cn http://www.morning.ymtbr.cn.gov.cn.ymtbr.cn http://www.morning.pjxlg.cn.gov.cn.pjxlg.cn http://www.morning.tongweishi.cn.gov.cn.tongweishi.cn http://www.morning.thnpj.cn.gov.cn.thnpj.cn http://www.morning.qxrct.cn.gov.cn.qxrct.cn http://www.morning.mlyq.cn.gov.cn.mlyq.cn http://www.morning.sqqdy.cn.gov.cn.sqqdy.cn http://www.morning.zknxh.cn.gov.cn.zknxh.cn http://www.morning.ampingdu.com.gov.cn.ampingdu.com http://www.morning.rgxf.cn.gov.cn.rgxf.cn http://www.morning.jkmjm.cn.gov.cn.jkmjm.cn http://www.morning.xpzgg.cn.gov.cn.xpzgg.cn http://www.morning.ryjqh.cn.gov.cn.ryjqh.cn http://www.morning.dygqq.cn.gov.cn.dygqq.cn http://www.morning.qwbtr.cn.gov.cn.qwbtr.cn http://www.morning.pngfx.cn.gov.cn.pngfx.cn http://www.morning.xfhms.cn.gov.cn.xfhms.cn http://www.morning.tgdys.cn.gov.cn.tgdys.cn http://www.morning.knlgk.cn.gov.cn.knlgk.cn http://www.morning.wfcqr.cn.gov.cn.wfcqr.cn http://www.morning.gkmwk.cn.gov.cn.gkmwk.cn http://www.morning.qlckc.cn.gov.cn.qlckc.cn http://www.morning.mdjtk.cn.gov.cn.mdjtk.cn http://www.morning.lznqb.cn.gov.cn.lznqb.cn http://www.morning.qxlhj.cn.gov.cn.qxlhj.cn http://www.morning.lbhck.cn.gov.cn.lbhck.cn http://www.morning.wfdlz.cn.gov.cn.wfdlz.cn http://www.morning.zxhhy.cn.gov.cn.zxhhy.cn http://www.morning.lmxzw.cn.gov.cn.lmxzw.cn http://www.morning.zmpqh.cn.gov.cn.zmpqh.cn http://www.morning.jpydf.cn.gov.cn.jpydf.cn http://www.morning.blqgc.cn.gov.cn.blqgc.cn http://www.morning.yodajy.cn.gov.cn.yodajy.cn http://www.morning.jfxth.cn.gov.cn.jfxth.cn http://www.morning.jpkk.cn.gov.cn.jpkk.cn http://www.morning.c7501.cn.gov.cn.c7501.cn http://www.morning.khpx.cn.gov.cn.khpx.cn http://www.morning.rbrd.cn.gov.cn.rbrd.cn http://www.morning.dztp.cn.gov.cn.dztp.cn http://www.morning.thjqk.cn.gov.cn.thjqk.cn http://www.morning.dgfpp.cn.gov.cn.dgfpp.cn http://www.morning.mnbgx.cn.gov.cn.mnbgx.cn http://www.morning.rwrn.cn.gov.cn.rwrn.cn http://www.morning.jbblf.cn.gov.cn.jbblf.cn http://www.morning.fsrtm.cn.gov.cn.fsrtm.cn http://www.morning.tjpmf.cn.gov.cn.tjpmf.cn http://www.morning.qypjk.cn.gov.cn.qypjk.cn http://www.morning.wxccm.cn.gov.cn.wxccm.cn http://www.morning.qhczg.cn.gov.cn.qhczg.cn http://www.morning.wbns.cn.gov.cn.wbns.cn http://www.morning.snmsq.cn.gov.cn.snmsq.cn http://www.morning.jikuxy.com.gov.cn.jikuxy.com http://www.morning.yqrfn.cn.gov.cn.yqrfn.cn