本文主要是介绍Go之errors.New和fmt.Errorf 的区别小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考...
error的基本用法
1. 获取错误信息
package main
import (
"errors"
"fmt"
)
func main() {
// 创建错误
err := errors.New("文件不存在")
// 获取错误信息
errorMessage := err.Error()
fmt.Println("错误信息:", errorMessage) // 输出: 错误信息: 文件不存在
// 直接打印错误
fmt.Println("直接打印:", err) // 输出: 直接打印: 文件不存在
}
2. 在条件判断中使用
package mahttp://www.chinasem.cnin
import (
"errors"
"fmt"
)
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 {
// 获取错误信息进行判断
if err.Error() == "除数不能为零" {
fmt.Println("检测到除零错误")
}
// 打印错误信息
fmt.Println("错误:", err.Error())
return
}
fmt.Println("结果:", result)
}
基本区别
1.函数签名
// errors.New - 只接受字符串
func New(text string) error
// fmt.Errorf - 接受格式化字符串和参数
func Errorf(format string, a ...interface{}) error
2.使用场景
package main
import (
"errors"
"fmt"
)
func main() {
// errors.New - 简单静态错误
err1 := errors.New("文件不存在")
fmt.Println(err1)
// fmt.Errorf - 动态格式化错误
filename := "config.txt"
err2 := fmt.Errorf("文件 %s 不存在", filename)
fmt.Printf("phperr: %v \n", err.Error())
}
详细对比
1. 静态错误 vs 动态错误
package main
import (
"errors"
"fmt"
)
// 使用 errors.New - 适合静态错误
var (
ErrNotFound = errors.New("记录未找到")
ErrInvalidInput = errors.New("无效输入")
ErrTimeout = errors.New("操作超时")
)
// 使用 fmt.Errorf - 适合动态错误
func validateAge(age int) error {
if age < 0 {
return fmt.Errorf("年龄不能为负数: %d", age)
}
if age > 150 {
return fmt.Errorf("年龄不能超过150岁: %d", age)
}
return nil
}
func main() {
// 静态错误
fmt.Println(ErrNotFound)
// 动态错误
err := validateAge(-5)
fmt.Println(err)
}
2. 错误比较
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("记录未找到")
func main() {
// errors.New 创建的错误可以用于比较
err1 := ErrNotFound
err2 := ErrNotFound
fmt.Println(err1 == err2) // true
// fmt.Errorf 创建的错误每次都是新的
err3 := fmt.Errorf("记录未找到")
err4 := fmt.Errorf("记录未找到")
fmt.Println(err3 == err4) // false
}
3. 错误包装
package main
import (
"errors"
"fmt"
)
func processFile(filename string) error {
// 模拟文件操作错误
originalErr := errors.New("权限不足")
// 使用 fmt.Errorf 包装错误
return fmt.Errorf("处理文件 %s 失败: %v", filename, originalErr)
}
func main() {
err := processFile("config.txt")
fmt.Println(err) // 输出: 处理文件 config.txt 失败: 权限不足
}
实际应用场景
1. 使用 errors.New 的场景
package main
import (
"errors"
"fmt"
)
// 定义包级别的错误常量
var (
ErrUserNotFound = errors.New("用户不存在")
ErrInvalidPassword = errors.New("密码错误")
ErrDatabaseConnection = errors.New("数据库连接失败")
)
func authenticateUser(userID string, password string) error {
if userID == "" {
return ErrUserNotFound
}
if password == "" {
return ErrInvalidPassword
}
// 验证逻辑...
return nil
}
func main() {
err := authenticateUser("", "123456")
if err == ErrUserNotFound {
fmt.Println("用户不存在")
} else if err == ErrInvalidPassword {
fmt.Println("密码错误")
}
}
2. 使用 fmt.Errorf 的场景
package main
import (
"fmt"
"strconv"
)
func parseUserID(userIDStr string) (int, error) {
userID, err := strconv.Atoi(userIDStr)
if err != nil {
return 0, fmt.Errorf("解析用户ID失败: %v", err)
}
if userID <= 0 {
return 0, fmt.Errorf("用户ID必须大于0,当前值: %d", userID)
}
return userID, nil
}
func getUserInfo(userIDStr string) error {
userID, err := parseUserID(userIDStr)
if err != nil {
return fmt.Errorf("获取用户信息失败: %v", err)
}
fmt.Printf("用户ID: %d\n", userID)
return nil
}
func main() {
err := getUserInfo("abc")
if err != nil {
fmt.Println("错误:", err)
}
}
自定义错误类型
1.基本用法
package main
import "fmt"
// 自定义错误类型
type ValidationError struct {
Field string
Message string
}
// 实现 Error() 方法
func (e *ValidationError) Error() string {
return fmt.Sprintf("验证失败: 字段 '%s' - %s", e.Field, e.Message)
}
func validateUser(name string) error {
if name == "" {
return &ValidationError{
Field: "name",
Message: "用户名不能为空",
}
}
return nil
}
func main() {
err := validateUser("")
if err != nil {
// 获取错误信息
fmt.Println("错DcBsXTjG误信息:", err.Error())
// 类型断言获取详细信息
if validationErr, ok := err.(*ValidationError); ok {
fmt.Printf("字段: %s, 消息: %s\n", validationErr.Field, validationErr.Message)
}
}
}
2.自定义错误类型示例
package main
import (
"fmt"
"time"
)
// 1. 基础自定义错误类型
type ValidationError struct {
Field string
Message string
Value interface{}
}
// 实现 error 接口
func (e *ValidationError) Error() string {
return fmt.Sprintf("验证失败: 字段 '%s' 的值 '%v' - %s", e.Field, e.Value, e.Message)
}
// 2. 业务错误类型
type BusinessError struct {
Code int
Message string
Time time.Time
}
func (e *BusinessError) Error() string {
return fmt.Sprintf("[%d] %s (时间: %s)", e.Code, e.Message, e.Time.Format("2006-01-02 15:04:05"))
}
// 3. 网络错误类型
type NetworkError struct {
URL string
Status int
Message string
}
func (e *NetworkError) Error() string {
return fmt.Sprintf("网络请求失败: %s (状态码: %d) - %s", e.URL, e.Status, e.Message)
}
// 4. 复合错误类型
type CompositeError strujsct {
Errors []error
Context string
}
func (e *CompositeError) Error() string {
if len(e.Errors) == 0 {
return fmt.Sprintf("复合错误: %s", e.Context)
}
result := fmt.Sprintf("复合错误 [%s]:\n", e.Context)
for i, err := range e.Errors {
result += fmt.Sprintf(" %d. %s\n", i+1, err.Error())
}
return result
}
// 5. 带错误码的错误类型
type CodedError struct {
Code int
Message string
Details map[string]interface{}
}
func (e *CodedError) Error() string {
if len(e.Details) == 0 {
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
return fmt.Sprintf("[%d] %s - 详情: %v", e.Code, e.Message, e.Details)
}
// 使用示例函数
func validateUser(name string, age int) error {
if name == "" {
return &ValidationError{
Field: "name",
Message: "用户名不能为空",
Value: name,
}
}
if age < 0 || age > 150 {
return &ValidationError{
Field: "age",
Message: "年龄必须在 0-150 之间",
Value: age,
}
}
return nil
}
func processOrder(orderID string) error {
if orderID == "" {
return &BusinessError{
Code: 1001,
Message: "订单ID不能为空",
Time: time.Now(),
}
}
// 模拟网络请求失败
if orderID == "invalid" {
return &NetworkError{
URL: "https://api.example.com/orders/" + orderID,
Status: 404,
Message: "订单不存在",
}
}
return nil
}
func complexOperation() error {
var errors []error
// 模拟多个操作
if err := validateUser("", 25); err != nil {
errors = append(errors, err)
}
if err := processOrder(""); err != nil {
errors = append(errors, err)
}
if len(errors) > 0 {
return &CompositeError{
Errors: errors,
Context: "用户注册操作",
}
}
return nil
}
func main() {
fmt.Println("=== 自定义错误类型示例 ===\n")
// 1. 验证错误示例
fmt.Println("1. 验证错误:")
if err := validateUser("", 25); err != nil {
fmt.Printf(" %s\n", err.Error())
}
if err := validateUser("张三", 200); err != nil {
fmt.Printf(" %s\n", err.Error())
}
// 2. 业务错误示例
fmt.Println("\n2. 业务错误:")
if err := processOrder(""); err != nil {
fmt.Printf(" %s\n", err.Error())
}
// 3. 网络错误示例
fmt.Println("\n3. 网络错误:")
if err := processOrder("invalid"); err != nil {
fmt.Printf(" %s\n", err.Error())
}
// 4. 复合错误示例
fmt.Println("\n4. 复合错误:")
if err := complexOperation(); err != nil {
fmt.Printf(" %s\n", err.Error())
}
// 5. 带错误码的错误示例
fmt.Println("\n5. 带错误码的错误:")
codedErr := &CodedError{
Code: 5001,
Message: "数据库连接失败",
Details: map[string]interface{}{
"host": "localhost:3306",
"database": "users",
"reason": "连接超时",
},
}
fmt.Printf(" %s\n", codedErr.Error())
// 6. 错误类型检查示例
fmt.Println("\n6. 错误类型检查:")
err := validateUser("", 25)
if validationErr, ok := err.(*ValidationError); ok {
fmt.Printf(" 这是一个验证错误,字段: %s\n", validationErrpython.Field)
}
if businessErr, ok := err.(*BusinessError); ok {
fmt.Printf(" 这是一个业务错误,错误码: %d\n", businessErr.Code)
}
}
到此这篇关于Go之errors.New 和 fmt.Errorf 的区别的文章就介绍到这了,更多相关Go errors.New 和 fmt.Errorf 内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Go之errors.New和fmt.Errorf 的区别小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!