我如何找出 go 中的错误是什么类型?
IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《我如何找出 go 中的错误是什么类型?》,聊聊,我们一起来看看吧!
我不确定如何确切地表达这个问题,而且我看到其他人问过类似的问题,但没有真正给出答案(这告诉我我问错了问题,但我不知道还能怎么做来解决这个问题)。
我正在尝试学习一些基本的 go,但在第一个障碍上就遇到了困难。
在我的测试代码中,我对一个不存在的域执行基本的 http get 操作,以触发 dns 警告。我发现 err.error() 返回一个字符串,因此为了断言它是否是 dns 错误,我使用了字符串比较:
resp, err := http.get(link)
if err != nil {
if strings.contains(err.error(), "no such host") == true {
return "no such host"
}
}
这显然是很hacky,所以我做了一些谷歌搜索,看看是否有更好的方法来找出引发了什么样的错误,我发现了以下答案:
如何检查特定的 golang net/http 错误代码?
包“errors”具有 as 功能,用于解包特定的错误类型,包“net”具有 *dnserror 类型。所以:
var dnserr *net.dnserror
if errors.as(err, &dnserr) {
...
}
这段代码有效,但我完全不知道这个结论是如何得出的。以下是我试图理解这一点的方法,我想知道我哪里出错了。我(模糊地)理解 .is() 和 .as() 正在做什么,但我不明白的是如何计算出什么错误“类型”来提供这些函数而无需猜测或先验知识。
我查看了这里的 client.get() 文档,上面写着:
任何返回的错误都将是 *url.error 类型。
更多的谷歌搜索,我发现我需要将错误转换(?)到该类型才能使用它:
urlerr := err.(*url.error)
*url.error 包含:
&url.error{op:"get", url:"http://doesnotexistkjdfhgsdfsdf.com", err:(*net.operror)(0xc00021a2d0)}
然后我查看 url.error 中包含的 net.operror:
netoperror := urlerr.err.(*net.operror)
fmt.printf("net op error contains: %#v\n", netoperror)
---
net op error contains: &net.operror{op:"dial", net:"tcp", source:net.addr(nil), addr:net.addr(nil), err:(*net.dnserror)(0xc0001a0040)}
然后我做同样的事情并“解压”net.operror 中包含的 net.dnserror:
dnsError := netOpError.Err.(*net.DNSError)
fmt.Printf("DNSError contains: %#v\n", dnsError)
---
DNSError contains: &net.DNSError{Err:"dial udp 169.254.169.254:53: connect: no route to host", Name:"doesnotexistkjdfhgsdfsdf.com", Server:"169.254.169.254:53", IsTimeout:false, IsTemporary:true, IsNotFound:false}
net.dnserror 不“包含”任何其他错误,所以对我来说,这表明它是链的底部和“真正的”错误(或者至少是我想要处理的错误)。 p>
事实是,这不是一个可行的方法,我不明白我们应该如何解决这个问题。在我发现第一篇 so 文章之前,我不知道 net.dnserror 是什么,也不知道我的错误可能是那种“类型”。
如果您不知道存在特定错误类型,并且函数调用可能属于该类型,您怎么知道?
我对 go 中的接口和类型的了解非常有限,我确信这对这里没有帮助,但对我来说,出现错误和知道要犯哪种错误之间似乎存在巨大的飞跃检查一下可能是这样。我希望这个问题有意义!
正确答案
首先,我建议阅读这篇博文:https://go.dev/blog/go1.13-errors
对您问题的简短回答:您是对的,要检查函数是否返回 net.dnserror 并访问其内部,您可以使用 errors.as 函数:
rsp, err := http.get(link)
dnserr := new(net.dnserror)
if errors.as(err, &dnserr) {
// use dnserr here
}
更新:从概念上讲,假设您知道可以处理的错误类型:因此您可以处理某些特定的错误(如果您可以处理)或将其返回到上层。在使用其他语言处理错误/异常时,这也是一种常见的做法。所以我的建议是:仅处理您知道如何处理的异常。对于 http 请求,通常是带有状态代码的 http 错误,dns 错误通常返回给调用者 func。
这是 errors 包中的函数示例的一些详细信息。
您可以使用 errors 包中的 errors.as 和 errrors.is 。例如,如果您有自定义类型的错误:
type myerror struct {
code int
}
您可以通过引用 errors.is() 检查未知错误:
var fooerr = &myerror{1}
func foo() (int, error) {...}
func main() {
_, err := foo()
fmt.printf("is fooerr? %v\n", errors.is(err, fooerr))
}
或者,如果您想实现自定义逻辑来比较错误(例如,在本例中通过 code),您可以将 is 方法添加到您的错误类型:
func (e *myerror) is(err error) bool {
as := new(myerror)
// i'll show as method later
if !errors.as(err, &as) {
return false
}
return e.code == as.code
}
此外,is 方法可以从包装类型中“解开”您的错误,例如如果要创建错误组合,可以使用 unwrap 方法添加一个新结构,或者使用 fmt.errorf 方法和 %w 参数:
type errwrap struct {
origin error
}
func (e *errwrap) unwrap() error {
return e.origin
}
func (e *errwrap) error() string {
return fmt.sprintf("wraps error '%s'", e.origin.error())
}
var fooerr = &myerror{1}
func foo() (int, error) {
return 0, &errwrap{origin: fooerr}
}
func main() {
_, err := foo()
fmt.printf("err == myerror? %v\n", err == fooerr) // false
fmt.printf("err is fooerr? %v\n", errors.is(err, &myerror{1})) // true
}
或者使用fmt.errorf:
err := fmt.errorf("wraps: %w", fooerr)
fmt.printf("err == myerror? %v\n", err == fooerr) // false
fmt.printf("err is fooerr? %v\n", errors.is(err, &myerror{1})) // true
另一个重要的方法是 errors.as,它的工作原理类似:您要么要检查错误的确切类型,要么对错误实现 as 方法,或者错误被另一个错误包裹:
err := &myerror{1}
as := new(myerror)
errors.as(err, &as)
fmt.printf("code: %v\n", as.code) // code: 1
或者使用 as 方法:
type anothererror struct {
anothercode int
}
func (e *anothererror) error() string {
return fmt.sprintf("code: %d", e.anothercode)
}
func (e *myerror) as(target interface{}) bool {
if out, ok := target.(**anothererror); ok {
(*out).anothercode = e.code
return true
}
return false
}
func main() {
err := &myerror{1}
as := new(anothererror)
errors.as(err, &as)
fmt.printf("code: %v\n", as.anothercode) // code: 1
}
包装也一样:
err := fmt.Errorf("wraps: %w", &myError{1})
as := new(myError)
errors.As(err, &as)
fmt.Printf("code: %v\n", as.code) // code: 1
今天关于《我如何找出 go 中的错误是什么类型?》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!
win7频繁出现程序停止工作怎么解决?
- 上一篇
- win7频繁出现程序停止工作怎么解决?
- 下一篇
- mac彩色打印删除文件?
-
- Golang · Go问答 | 1年前 |
- 在读取缓冲通道中的内容之前退出
- 139浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 戈兰岛的全球 GOPRIVATE 设置
- 204浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将结构作为参数传递给 xml-rpc
- 325浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何用golang获得小数点以下两位长度?
- 478浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何通过 client-go 和 golang 检索 Kubernetes 指标
- 486浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将多个“参数”映射到单个可变参数的习惯用法
- 439浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将 HTTP 响应正文写入文件后出现 EOF 错误
- 357浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 结构中映射的匿名列表的“复合文字中缺少类型”
- 352浏览 收藏
-
- Golang · Go问答 | 1年前 |
- NATS Jetstream 的性能
- 101浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将复杂的字符串输入转换为mapstring?
- 440浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 相当于GoLang中Java将Object作为方法参数传递
- 212浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何确保所有 goroutine 在没有 time.Sleep 的情况下终止?
- 143浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3206次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3419次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3449次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4557次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3827次使用
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- Golang取得代码运行时间的问题
- 2023-02-24 501浏览
-
- 请问 go 代码如何实现在代码改动后不需要Ctrl+c,然后重新 go run *.go 文件?
- 2023-01-08 501浏览
-
- 如何从同一个 io.Reader 读取多次
- 2023-04-11 501浏览

