Golang中Error()返回结构体的实现方法

Golang中Error()返回结构体的实现方法 你好,

我定义了一个实现了 error 接口的自定义错误。但我希望 Error() 函数返回一个结构体而不是字符串。这可能吗?或者有没有什么方法可以让我使用函数返回的状态码和错误信息。

示例:

package main

import (
    "errors"
    "fmt"
    "os"
)

type RequestError struct {
    StatusCode int

    Msg string
}

func (r *RequestError) Error() string {
    return fmt.Sprintf("status %d: err %s", r.StatusCode, r.Msg)
}

func doRequest() error {
    return &RequestError{
        StatusCode: 503,
        Msg:        "unavailable",
    }
}

func main() {
    err := doRequest()
    if err != nil {
        fmt.Println(err)
       // fmt.Println(err.StatusCode)
       // fmt.Println(err.Msg)
        os.Exit(1)
    }
    fmt.Println("success!")
}

就像我在 main 函数中注释掉的部分那样。

这可能吗?

提前感谢。


更多关于Golang中Error()返回结构体的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

结构体中的 Err 字段缺失:

package main

import (
	"fmt"
	"os"
)

type RequestError struct {
	StatusCode int
	Msg        string
	Err        string
}

func (r *RequestError) Error() string {
	return fmt.Sprintf("status %d: err %s", r.StatusCode, r.Msg)
}

func doRequest() error {
	return &RequestError{
		StatusCode: 503,
		Err:        "unavailable",
	}
}

func main() {
	err := doRequest()
	if err != nil {
		fmt.Println(err)
		// fmt.Println(err.StatusCode)
		// fmt.Println(err.Msg)
		os.Exit(1)
	}
	fmt.Println("success!")
}

更多关于Golang中Error()返回结构体的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我定义了一个实现了 error 接口的自定义错误。但我希望 Error() 函数返回一个结构体而不是字符串。

不,error 接口的定义是:

type error interface {
    Error() string
}

如果你返回的不是 string,那么你的自定义错误将不再被视为一个 error,因为签名不匹配。

你为什么想从 Error 函数返回非字符串的内容呢?

编辑:我误点了保存 🙂

你应该将你的 main 函数修改为这样:

	if err != nil {
		fmt.Println(err)
		if re, ok := err.(*RequestError); ok {
			fmt.Println(re.StatusCode)
			fmt.Println(re.Msg)
		}
		os.Exit(1)
	}

在Go语言中,error接口的Error()方法必须返回字符串,这是接口的约定。不过,你可以通过类型断言来访问自定义错误结构体的字段。以下是几种实现方法:

1. 类型断言直接访问

func main() {
    err := doRequest()
    if err != nil {
        // 类型断言访问具体字段
        if reqErr, ok := err.(*RequestError); ok {
            fmt.Printf("Status Code: %d\n", reqErr.StatusCode)
            fmt.Printf("Message: %s\n", reqErr.Msg)
        }
        fmt.Println(err) // 调用 Error() 方法
        os.Exit(1)
    }
    fmt.Println("success!")
}

2. 添加辅助方法返回结构体

// 在 RequestError 中添加方法
func (r *RequestError) Details() RequestError {
    return *r
}

// 使用示例
func main() {
    err := doRequest()
    if err != nil {
        if reqErr, ok := err.(*RequestError); ok {
            details := reqErr.Details()
            fmt.Printf("Status: %d, Msg: %s\n", 
                details.StatusCode, details.Msg)
        }
        os.Exit(1)
    }
}

3. 使用 errors.As 进行类型匹配(Go 1.13+)

func main() {
    err := doRequest()
    var reqErr *RequestError
    if errors.As(err, &reqErr) {
        fmt.Printf("Status Code: %d\n", reqErr.StatusCode)
        fmt.Printf("Message: %s\n", reqErr.Msg)
        os.Exit(1)
    }
    fmt.Println("success!")
}

4. 完整示例代码

package main

import (
    "errors"
    "fmt"
    "os"
)

type RequestError struct {
    StatusCode int
    Msg        string
}

func (r *RequestError) Error() string {
    return fmt.Sprintf("status %d: err %s", r.StatusCode, r.Msg)
}

func (r *RequestError) Details() RequestError {
    return *r
}

func doRequest() error {
    return &RequestError{
        StatusCode: 503,
        Msg:        "unavailable",
    }
}

func main() {
    err := doRequest()
    if err != nil {
        // 方法1:类型断言
        if reqErr, ok := err.(*RequestError); ok {
            fmt.Printf("Type Assertion - Status: %d, Msg: %s\n",
                reqErr.StatusCode, reqErr.Msg)
        }

        // 方法2:使用 Details 方法
        if reqErr, ok := err.(*RequestError); ok {
            details := reqErr.Details()
            fmt.Printf("Details Method - Status: %d, Msg: %s\n",
                details.StatusCode, details.Msg)
        }

        // 方法3:errors.As
        var reqErr *RequestError
        if errors.As(err, &reqErr) {
            fmt.Printf("errors.As - Status: %d, Msg: %s\n",
                reqErr.StatusCode, reqErr.Msg)
        }

        fmt.Println("Error string:", err.Error())
        os.Exit(1)
    }
    fmt.Println("success!")
}

5. 链式错误处理示例

func handleError(err error) {
    var reqErr *RequestError
    switch {
    case errors.As(err, &reqErr):
        fmt.Printf("RequestError: Code=%d, Msg=%s\n",
            reqErr.StatusCode, reqErr.Msg)
    default:
        fmt.Printf("Generic error: %v\n", err)
    }
}

func main() {
    err := doRequest()
    handleError(err)
}

虽然Error()方法必须返回字符串,但通过这些方法你可以在需要时访问错误结构体的所有字段信息。

回到顶部