当前位置:网站首页>学习 Go 语言 0x08:《Go 语言之旅》中 练习使用 error
学习 Go 语言 0x08:《Go 语言之旅》中 练习使用 error
2022-04-23 11:02:00 【爱博客大伯】
* 题目
https://tour.go-zh.org/methods/20
练习:错误
从之前的练习中复制 Sqrt 函数,修改它使其返回 error
值。
Sqrt 接受到一个负数时,应当返回一个非 nil 的错误值。复数同样也不被支持。
创建一个新的类型
type ErrNegativeSqrt float64
并为其实现
func (e ErrNegativeSqrt) Error() string
方法使其拥有 error
值,通过 ErrNegativeSqrt(-2).Error()
调用该方法应返回 "cannot Sqrt negative number: -2"
。
注意: 在 Error 方法内调用 fmt.Sprint(e)
会让程序陷入死循环。可以通过先转换 e 来避免这个问题:fmt.Sprint(float64(e))
。这是为什么呢?
修改 Sqrt
函数,使其接受一个负数时,返回 ErrNegativeSqrt
值。
* 代码
package main
import (
"fmt"
)
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error() string {
return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
}
func Sqrt(x float64) (float64, error) {
if x < 0 {
return 0, ErrNegativeSqrt(x)
}
z := 1.0
for i := 1; i < 10; i++ {
z -= (z*z - x) / (2*z)
}
return z, nil
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
输出:
1.4142135623730951 <nil>
0 cannot Sqrt negative number: -2
* 将 fmt.Sprint(float64(e))
改为 fmt.Sprint(e)
, 将会栈溢出
如果 把 fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
改成 fmt.Sprintf("cannot Sqrt negative number: %v", e)
,运行结果为:
1.4142135623730951 <nil>
runtime: goroutine stack exceeds 250000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x1054d9, 0xe)
/usr/local/go/src/runtime/panic.go:617 +0x80
runtime.newstack()
/usr/local/go/src/runtime/stack.go:1041 +0x960
runtime.morestack()
/usr/local/go/src/runtime/asm_amd64p32.s:299 +0xc0
goroutine 1 [running]:
sync.(*Mutex).Lock(0x3422094, 0x0)
/usr/local/go/src/sync/mutex.go:72 +0x3a0 fp=0x8c00360 sp=0x8c00358 pc=0x99b80
sync.(*Pool).getSlow(0x1ad078, 0x8, 0x3422080, 0x0)
/usr/local/go/src/sync/pool.go:165 +0xe0 fp=0x8c00390 sp=0x8c00360 pc=0x9a400
sync.(*Pool).Get(0x1ad078, 0x1b4540, 0xfefc0004, 0x0)
/usr/local/go/src/sync/pool.go:141 +0x1a0 fp=0x8c003b8 sp=0x8c00390 pc=0x9a2a0
fmt.newPrinter(0x8c003f0, 0x0)
/usr/local/go/src/fmt/print.go:134 +0x40 fp=0x8c003d0 sp=0x8c003b8 pc=0xce6e0
fmt.Sprintf(0x1082ef, 0x1f, 0x8c00420, 0x1, 0x1, 0x8c00438, 0x18, 0x139f)
/usr/local/go/src/fmt/print.go:213 +0x20 fp=0x8c00400 sp=0x8c003d0 pc=0xcec40
main.ErrNegativeSqrt.Error(...)
/tmp/sandbox804641635/main.go:10
main.(*ErrNegativeSqrt).Error(0x67a3330, 0x122ecc, 0x67c7300, 0xf1b40)
<autogenerated>:1 +0xc0 fp=0x8c00430 sp=0x8c00400 pc=0xd97c0
fmt.(*pp).handleMethods(0x67c7300, 0x76, 0x6cd01, 0x139f)
/usr/local/go/src/fmt/print.go:610 +0x1e0 fp=0x8c00480 sp=0x8c00430 pc=0xd2480
fmt.(*pp).printArg(0x67c7300, 0xf1b40, 0x67a3330, 0x76)
/usr/local/go/src/fmt/print.go:699 +0x260 fp=0x8c004d0 sp=0x8c00480 pc=0xd2d00
fmt.(*pp).doPrintf(0x67c7300, 0x1082ef, 0x1f, 0x8c00598, 0x1, 0x1)
/usr/local/go/src/fmt/print.go:1016 +0x180 fp=0x8c00548 sp=0x8c004d0 pc=0xd7640
fmt.Sprintf(0x1082ef, 0x1f, 0x8c00598, 0x1, 0x1, 0x8c005b0, 0x18, 0x139f)
/usr/local/go/src/fmt/print.go:214 +0x60 fp=0x8c00578 sp=0x8c00548 pc=0xcec80
main.ErrNegativeSqrt.Error(...)
/tmp/sandbox804641635/main.go:10
略 (还有很多log)
对代码死循环的理解:
有问题的代码,如下:
func (e ErrNegativeSqrt) Error() string {
return fmt.Sprintf("cannot Sqrt negative number: %v", e)
}
第一次执行 ErrNegativeSqrt
的 Error()
函数,是由 main
函数中的 fmt.Println(Sqrt(-2))
触发的。Sqrt(-2)
返回 error 为 ErrNegativeSqrt
,在main
中打印这个 error,就会执行 ErrNegativeSqrt
的 Error()
函数。
然后在 Error()
函数内部,执行 fmt.Sprintf("cannot Sqrt negative number: %v", e)
,e
为ErrNegativeSqrt
,所以,再一次打印 ErrNegativeSqrt
,所以,还会调用 ErrNegativeSqrt
的 Error()
函数。这样就出现了死循环,直到调用栈溢出报错。
版权声明
本文为[爱博客大伯]所创,转载请带上原文链接,感谢
https://blog.csdn.net/u013553529/article/details/88919789
边栏推荐
- Embedded related surface (I)
- Facing the global market, platefarm today logs in to four major global platforms such as Huobi
- Intuitive understanding entropy
- Manjaro installation and configuration (vscode, wechat, beautification, input method)
- Resolution and size of mainstream mobile phones
- 软件测试人员,如何优秀的提Bug?
- Notes on concurrent programming of vegetables (V) thread safety and lock solution
- colab
- Special members and magic methods
- Swagger2 自定义参数注解如何不显示
猜你喜欢
After the MySQL router is reinstalled, it reconnects to the cluster for boot - a problem that has been configured in this host before
Ueditor -- limitation of 4m size of image upload component
Diary of dishes | Blue Bridge Cup - hexadecimal to octal (hand torn version) with hexadecimal conversion notes
Visualization Road (11) detailed explanation of Matplotlib color
Solution architect's small bag - 5 types of architecture diagrams
Charles 功能介绍和使用教程
Mysql8.0安装指南
MySQL how to merge the same data in the same table
Visual solutions to common problems (VIII) mathematical formulas
Excel·VBA自定义函数获取单元格多数值
随机推荐
图像处理——噪声小记
Image processing - Noise notes
一个微博数据库设计带来的简单思考
Read integrity monitoring techniques for vision navigation systems
Full stack cross compilation x86 completion process experience sharing
Visual Road (XII) detailed explanation of collection class
Latex usage
Chapter 120 SQL function round
Visualization Road (10) detailed explanation of segmentation canvas function
Google Earth Engine(GEE)——将原始影像进行升尺度计算(以海南市为例)
软件测试人员,如何优秀的提Bug?
The courses bought at a high price are open! PHPer data sharing
最强日期正则表达式
Learning note 5 - gradient explosion and gradient disappearance (k-fold cross verification)
【leetcode】102.二叉树的层序遍历
Difference between pregnancy box and delivery box
Full stack cross compilation x86 completion process experience sharing
Charles 功能介绍和使用教程
MySQL common statements
Reading integrity monitoring techniques for vision navigation systems - 5 Results