使用Go标准库errors.As无法解包自定义错误类型的问题
问题原因分析
你的代码存在两个关键问题:
- 类型不匹配:
retError()返回的是*myError指针类型的错误,但main中声明的目标变量m是myError值类型。errors.As会严格匹配错误的动态类型,因此无法将*myError赋值给myError类型的目标,导致匹配失败。 - 未实现错误解包接口:你的
myError结构体没有实现Unwrap() error方法,即使匹配到myError实例,也无法通过errors.As递归解开它包装的底层错误。
修正后的代码
以下是同时解决两个问题的完整代码:
package main import ( "errors" "fmt" ) type myError struct { err error } func (m myError) Error() string { return fmt.Sprintf("my error: %s", m.err) } // 实现Unwrap方法,支持错误链解包 func (m myError) Unwrap() error { return m.err } func retError() error { return &myError{errors.New("wrapped")} } func main() { var m *myError // 将目标变量改为指针类型 err := retError() if errors.As(err, &m) { fmt.Println("unwrapped", m.err) // 可选:进一步解包底层错误 var wrappedErr *errors.errorString if errors.As(err, &wrappedErr) { fmt.Println("底层原始错误:", wrappedErr) } } else { fmt.Println(err) } }
关键说明
- 类型匹配调整:当错误是指针类型(
*myError)时,errors.As的目标参数需要是指向该指针的指针(即**myError),因此声明var m *myError并传入&m才能匹配成功。 - Unwrap方法的作用:实现该方法后,
errors.As可以递归遍历错误链,不仅能匹配myError本身,还能直接定位到它包装的底层错误。如果仅需获取myError实例,可省略Unwrap方法,但你的需求是提取底层错误,因此必须实现它。
内容的提问来源于stack exchange,提问作者renbou
相关产品推荐
相关产品推荐

