为什么Go中有的自定义error会导致内存溢出
分享一个在go tour上看到的练习题,练习里要求用户自己定义一个错误类型,实现error
接口,函数在参数不满足条件的时候返回自定义的错误类型的值。练习中特别提示用户不要在实现的Error
方法里直接使用fmt.Sprint(e)
以避免造成程序内存溢出。
下面贴一下具体的练习题
Practice
从之前的练习中复制 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
值。
Solution
这里只为叙述返回error的情况,所以请忽略Sqrt函数的功能实现。
package mainimport ("fmt"
)type ErrNegativeSqrt float64func (e ErrNegativeSqrt) Error() string {// 这里直接使用e值会内存溢出return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
}func Sqrt(x float64) (float64, error) {if x < 0 {err := ErrNegativeSqrt(x)return 0, err}return 0, nil
}func main() {fmt.Println(Sqrt(2))fmt.Println(Sqrt(-2))
}
接下来探究一下为什么在练习中把值e
先转换为float64类型后程序就不会再内存溢出。
fmt.Sprint(e)
将调用e.Error()
将e
转换为字符串。如果Error()
方法调用fmt.Sprint(e)
,则程序将递归直到内存溢出。可以通过将e
转换成一个非错误类型(未实现Error接口)的值来避免这种情况。
实际上在Error
方法中把error
值直接传递给fmt
包中Print相关的函数都会导致无限循环。原因可以在fmt包的源码中找到。
switch verb {case 'v', 's', 'x', 'X', 'q':// Is it an error or Stringer?// The duplication in the bodies is necessary:// setting wasString and handled, and deferring catchPanic,// must happen before calling the method.switch v := p.field.(type) {case error:wasString = falsehandled = truedefer p.catchPanic(p.field, verb)// 这里调用了Error方法p.printField(v.Error(), verb, plus, false, depth)return
通过链接可以在Github上看到这块详细的源码 https://github.com/golang/go/...
这个练习感觉还是给开发者提示了一个非常隐蔽的坑,感兴趣的可以去go tour上的这个练习题自己试验一下。
课程推荐:简明高效的Go语言入门和实战指南
为什么Go中有的自定义error会导致内存溢出相关推荐
- 为什么Go的自定义error有时候会内存溢出
分享一个在go tour上看到的练习题,练习里要求用户自己定义一个错误类型,实现 error接口,函数在参数不满足条件的时候返回自定义的错误类型的值.练习中特别提示用户不要在实现的 Error方法里直 ...
- kera中使用keras.banked.ctc_decoder()导致内存不断增加的问题解决
kera中使用keras.banked.ctc_decoder()导致内存不断增加的问题解决 遇到的问题 在使用keras训练了模型后,使用模型进行测试,测试过程中发现随着测试数据的增加,测试速度不断 ...
- 图片--Android加载图片导致内存溢出(Out of Memory异常)
Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证) ...
- Android加载图片导致内存溢出(Out of Memory异常)
Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证) ...
- POI读写超大数据量Excel,解决超过几万行而导致内存溢出的问题(附源码)
来源:cnblogs.com/swordfall/p/8298386.html 1. Excel2003与Excel2007 两个版本的最大行数和列数不同,2003版最大行数是65536行,最大列数是 ...
- 添加IFrame导致内存溢出的解决过程(IE浏览器,目前发现了原因,还未解决)...
1. 现象 每次动态添加iframe时,iexplore.exe进程占据的内存都会增加(大概10M左右),不会自动释放,最终导致内存溢出 2. 解决过程 经过网络的一番搜索,基本上给出的解决方案是 ...
- 本地项目antd 修改.less文件导致内存溢出
项目场景: antd 项目,修改less文件会导致内存溢出 问题描述 本地环境antd 项目,修改less文件会导致内存溢出:如下 FATAL ERROR: Reached heap limit Al ...
- php查询mysql返回大量数据结果集导致内存溢出的解决方法
web开发中如果遇到php查询mysql返回大量数据导致内存溢出.或者内存不够用的情况那就需要看下MySQL C API的关联,那么究竟是什么导致php查询mysql返回大量数据时内存不够用情况? 答 ...
- android 内存溢出检查,Android Handler使用导致内存溢出附带LeakCanary排查
最近项目马上结束了在对项目进行检查有没有内存泄漏的地方,这里使用的是leakcanary. 使用步骤很简单: 添加依赖: dependencies { debugCompile 'com.square ...
最新文章
- 回顾与展望:大热的AutoML究竟是什么? | 技术头条
- flutter listview 滚动到底部_Flutter常用Widget详解(三)
- VMware网络配置详解
- com/android/dx/command/dexer/Main : Unsupported major.minor version 52.0
- 11.14/11.15 Apache和PHP结合 11.16/11.17 Apache默认虚拟主机
- 使用SAP open connector调用第三方系统的API
- 9、java中的异常处理机制
- 解决Ajax中IE浏览器缓存问题
- java 管道流_Java IO7:管道流、对象流
- 【转载】大型网站性能
- linux键盘映射默认,Linux 中的键盘映射【转】
- 基于SpringBoot的统计报表后台管理系统
- 对偶式与反函数_图解数字电路中标准式的对偶式和反函数求解
- stony大学计算机科学找工作,美国STEM专业毕业生薪资最高的院校有哪些?
- 基于Nebula3的游戏: 龙歌:黑暗之眼 试玩下载
- 软件开发者的终极梦想:揭秘谷歌编程面试
- CSS鼠标划过背景渐变效果
- @Value取不到值的原因
- brew cask安装软件提示:Error: Unknown command: cask
- 访傲林科技董事长刘震:用企业级数字孪生掘金工业互联网
热门文章
- FastRoute - 快速请求路由
- 神经科学与“记忆印记”
- 在windows下使用Xming+Putty显示Linux下软件图形界面
- Mac清理软件为苹果系统迅速减压
- Java UDP和TCP的区别
- GlobalSign 团队与世界领先的认证机构(CAs)合作 共同加强网络安全
- 2012年十大项目月度得分榜
- 解决 python中 使用tesserocr,File tesserocr.pyx, line 2401, in tesserocr._tesserocr.image_to_text 报错问题...
- Idea创建简单Java Web项目并部署Servlet
- 安装System Center 2012 R2 数据库