分享一个在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会导致内存溢出相关推荐

  1. 为什么Go的自定义error有时候会内存溢出

    分享一个在go tour上看到的练习题,练习里要求用户自己定义一个错误类型,实现 error接口,函数在参数不满足条件的时候返回自定义的错误类型的值.练习中特别提示用户不要在实现的 Error方法里直 ...

  2. kera中使用keras.banked.ctc_decoder()导致内存不断增加的问题解决

    kera中使用keras.banked.ctc_decoder()导致内存不断增加的问题解决 遇到的问题 在使用keras训练了模型后,使用模型进行测试,测试过程中发现随着测试数据的增加,测试速度不断 ...

  3. 图片--Android加载图片导致内存溢出(Out of Memory异常)

    Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory  Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证) ...

  4. Android加载图片导致内存溢出(Out of Memory异常)

    Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory  Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证) ...

  5. POI读写超大数据量Excel,解决超过几万行而导致内存溢出的问题(附源码)

    来源:cnblogs.com/swordfall/p/8298386.html 1. Excel2003与Excel2007 两个版本的最大行数和列数不同,2003版最大行数是65536行,最大列数是 ...

  6. 添加IFrame导致内存溢出的解决过程(IE浏览器,目前发现了原因,还未解决)...

    1.  现象 每次动态添加iframe时,iexplore.exe进程占据的内存都会增加(大概10M左右),不会自动释放,最终导致内存溢出 2.  解决过程 经过网络的一番搜索,基本上给出的解决方案是 ...

  7. 本地项目antd 修改.less文件导致内存溢出

    项目场景: antd 项目,修改less文件会导致内存溢出 问题描述 本地环境antd 项目,修改less文件会导致内存溢出:如下 FATAL ERROR: Reached heap limit Al ...

  8. php查询mysql返回大量数据结果集导致内存溢出的解决方法

    web开发中如果遇到php查询mysql返回大量数据导致内存溢出.或者内存不够用的情况那就需要看下MySQL C API的关联,那么究竟是什么导致php查询mysql返回大量数据时内存不够用情况? 答 ...

  9. android 内存溢出检查,Android Handler使用导致内存溢出附带LeakCanary排查

    最近项目马上结束了在对项目进行检查有没有内存泄漏的地方,这里使用的是leakcanary. 使用步骤很简单: 添加依赖: dependencies { debugCompile 'com.square ...

最新文章

  1. 回顾与展望:大热的AutoML究竟是什么? | 技术头条
  2. flutter listview 滚动到底部_Flutter常用Widget详解(三)
  3. VMware网络配置详解
  4. com/android/dx/command/dexer/Main : Unsupported major.minor version 52.0
  5. 11.14/11.15 Apache和PHP结合 11.16/11.17 Apache默认虚拟主机
  6. 使用SAP open connector调用第三方系统的API
  7. 9、java中的异常处理机制
  8. 解决Ajax中IE浏览器缓存问题
  9. java 管道流_Java IO7:管道流、对象流
  10. 【转载】大型网站性能
  11. linux键盘映射默认,Linux 中的键盘映射【转】
  12. 基于SpringBoot的统计报表后台管理系统
  13. 对偶式与反函数_图解数字电路中标准式的对偶式和反函数求解
  14. stony大学计算机科学找工作,美国STEM专业毕业生薪资最高的院校有哪些?
  15. 基于Nebula3的游戏: 龙歌:黑暗之眼 试玩下载
  16. 软件开发者的终极梦想:揭秘谷歌编程面试
  17. CSS鼠标划过背景渐变效果
  18. @Value取不到值的原因
  19. brew cask安装软件提示:Error: Unknown command: cask
  20. 访傲林科技董事长刘震:用企业级数字孪生掘金工业互联网

热门文章

  1. FastRoute - 快速请求路由
  2. 神经科学与“记忆印记”
  3. 在windows下使用Xming+Putty显示Linux下软件图形界面
  4. Mac清理软件为苹果系统迅速减压
  5. Java UDP和TCP的区别
  6. GlobalSign 团队与世界领先的认证机构(CAs)合作 共同加强网络安全
  7. 2012年十大项目月度得分榜
  8. 解决 python中 使用tesserocr,File tesserocr.pyx, line 2401, in tesserocr._tesserocr.image_to_text 报错问题...
  9. Idea创建简单Java Web项目并部署Servlet
  10. 安装System Center 2012 R2 数据库