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 函数。