Golang fmt.Errorf 函数
最后修改时间 2025 年 5 月 8 日
本教程将讲解如何在 Go 中使用 fmt.Errorf
函数。我们将通过格式化错误的实际示例,涵盖错误创建基础知识。
fmt.Errorf
函数使用格式化的消息创建错误值。它的工作方式类似于 fmt.Printf
,但返回错误而不是打印输出。这对于创建描述性的错误消息非常有用。
在 Go 中,fmt.Errorf
通常用于用额外的上下文包装错误。它支持 fmt.Printf
中所有可用的格式化动词。该函数返回一个实现 error 接口的错误值。
fmt.Errorf 的基本用法示例
fmt.Errorf
最简单的用法是创建一个带有静态消息的错误。此示例演示了基本的错误创建。
注意: 错误消息可以包含任何格式说明符。
package main import ( "fmt" "log" ) func divide(a, b int) (int, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil } func main() { result, err := divide(10, 0) if err != nil { log.Fatal(err) } fmt.Println("Result:", result) }
当尝试除以零时,该函数返回一个格式化的错误。main 函数检查错误并在存在时记录它。
格式化错误消息
fmt.Errorf
支持所有标准的格式化动词。此示例展示了如何将动态值包含在错误消息中。
package main import ( "fmt" "os" ) func checkFileSize(filename string, maxSize int64) error { info, err := os.Stat(filename) if err != nil { return err } if info.Size() > maxSize { return fmt.Errorf("file %s is too large (%d bytes > max %d bytes)", filename, info.Size(), maxSize) } return nil } func main() { err := checkFileSize("data.txt", 1024) if err != nil { fmt.Println("Error:", err) } }
错误消息包含文件名、实际大小和最大大小。这提供了有关出错内容的详细上下文。
使用 fmt.Errorf 包装错误
fmt.Errorf
可以使用 %w
动词来包装现有错误。此示例展示了如何在保留原始错误的同时添加上下文。
package main import ( "errors" "fmt" "os" ) func readConfig(file string) ([]byte, error) { data, err := os.ReadFile(file) if err != nil { return nil, fmt.Errorf("failed to read config file %s: %w", file, err) } return data, nil } func main() { _, err := readConfig("missing.conf") if err != nil { fmt.Println("Error:", err) var pathErr *os.PathError if errors.As(err, &pathErr) { fmt.Println("Underlying path error:", pathErr) } } }
%w
动词在添加上下文的同时包装了原始错误。main 函数仍然可以使用 errors.As
访问底层错误。
包含多个值的错误
fmt.Errorf
可以将多个值格式化到错误消息中。此示例展示了一个包含多个动态值的复杂错误。
package main import ( "fmt" "time" ) func scheduleEvent(name string, when time.Time) error { if when.Before(time.Now()) { return fmt.Errorf("cannot schedule %s at %v (in the past, now is %v)", name, when.Format(time.RFC3339), time.Now().Format(time.RFC3339)) } return nil } func main() { pastTime := time.Now().Add(-1 * time.Hour) err := scheduleEvent("meeting", pastTime) if err != nil { fmt.Println("Error:", err) } }
错误包括事件名称、计划时间和当前时间。所有值都已正确格式化,以便清晰地报告错误。
使用 fmt.Errorf 定义自定义错误类型
fmt.Errorf
可以与自定义错误类型一起使用。此示例展示了如何将格式化消息与结构化错误数据结合起来。
package main import ( "errors" "fmt" ) type ValidationError struct { Field string Message string } func (e ValidationError) Error() string { return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message) } func validateUser(name string, age int) error { if name == "" { return fmt.Errorf("user validation: %w", ValidationError{Field: "name", Message: "cannot be empty"}) } if age < 0 { return fmt.Errorf("user validation: %w", ValidationError{Field: "age", Message: "must be positive"}) } return nil } func main() { err := validateUser("", -1) if err != nil { fmt.Println("Error:", err) var valErr ValidationError if errors.As(err, &valErr) { fmt.Printf("Field %s failed: %s\n", valErr.Field, valErr.Message) } } }
自定义的 ValidationError
提供了结构化的错误信息。fmt.Errorf
在添加额外上下文的同时包装了这些错误。
包含位置信息的错误
fmt.Errorf
可以在错误中包含调用者信息。此示例展示了如何创建包含文件和行号详细信息的错误。
package main import ( "fmt" "runtime" ) func doSomething() error { _, file, line, _ := runtime.Caller(1) return fmt.Errorf("error at %s:%d - invalid operation", file, line) } func main() { err := doSomething() if err != nil { fmt.Println("Error:", err) } }
runtime.Caller
函数获取调用者的文件和行号。此信息包含在格式化的错误消息中。
条件错误格式化
fmt.Errorf
可以与条件逻辑一起使用以创建不同的错误消息。此示例展示了动态错误消息生成。
package main import ( "fmt" "strings" ) func processInput(input string) error { if len(input) == 0 { return fmt.Errorf("input error: empty string provided") } if strings.Contains(input, "error") { return fmt.Errorf("input error: contains forbidden word 'error'") } if len(input) > 100 { return fmt.Errorf("input error: length %d exceeds maximum of 100", len(input)) } return nil } func main() { tests := []string{"", "test with error", strings.Repeat("a", 101)} for _, test := range tests { err := processInput(test) if err != nil { fmt.Printf("'%s' → %v\n", test, err) } } }
不同的错误条件会生成不同的格式化消息。该函数根据输入验证返回适当的错误。
来源
本教程通过实际的格式化错误创建和包装示例,介绍了 Go 中的 fmt.Errorf
函数。