你能答对这道 Go 题目吗过 80% 的人都答错了...
最近在冲浪的时候,看到 Redhat 首席软件工程师、Prometheus 等项目的维护者 Bartłomiej Płotka 在 twitter 上出了一道 Go 的 “考题”,说是要来考考大家。
题目如下:
func aaa() (done func(), err error) {
return func() {
print("aaa: done")
}, nil
}
func bbb() (done func(), _ error) {
done, err := aaa()
return func() {
print("bbb: surprise!");
done()
}, err
}
func main() {
done, _ := bbb()
done()
}
答案的选项如下:
一道 Go 考题(单选)
想想原因,思考一下输出结果是什么?是 A,还是 D?还是三短一长,选 B?
分析程序
缩小范围,核心关注到这块代码。如下:
func bbb() (done func(), _ error) {
done, err := aaa()
return func() {
print("bbb: surprise!")
done()
}, err
}
在最后一行的这个闭包(匿名函数)中,大家可能认为程序调用了函数 aaa
所返回的 done
值来输出程序,应当是:
aaa: done
这个想法是错误的,程序没有这么去运作。
原因在于 return
实际上是一个赋值语句。结合程序,可以看到函数 bbb
的第一个返回值是 done
参数。
如下:
func bbb() (done func(), _ error)
也就是在函数 bbb
在程序最后执行 return
语句后,会对返回变量 done
进行赋值,自然该值不会是由函数 aaa
所设置的了。
这是一个关键的地方。
具体过程
这个程序输出结果是什么呢?
他会不断地递归,疯狂输出 “bbb: surprise!”,直至栈溢出,导致程序运行出错,最终中止
同学就疑惑了,怎么又多出了个递归?
我们再看看程序:
func main() {
done, _ := bbb()
done()
}
func bbb() (done func(), _ error) {
...
return func() {
print("bbb: surprise!");
done()
}, err
}
本质上在函数 bbb
执行完毕后, 变量 done
已经变成了一个递归函数。
递归的过程是:函数 bbb
调用变量 done
后,会输出 bbb: surprise!
字符串,然后又调用变量 done
。而变量 done
又是这个闭包(匿名函数),从而实现不断递归调用和输出。
最终结果如下:
b: surprise!bbb: surprise!bbb: surprise!runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc0200e0380 stack=[0xc0200e0000, 0xc0400e0000]
fatal error: stack overflow
runtime stack:
runtime.throw(0x1074b5a, 0xe)
/usr/local/Cellar/go/1.16.6/libexec/src/runtime/panic.go:1117 0x72
runtime.newstack()
/usr/local/Cellar/go/1.16.6/libexec/src/runtime/stack.go:1069 0x7ed
runtime.morestack()
/usr/local/Cellar/go/1.16.6/libexec/src/runtime/asm_amd64.s:458 0x8f
...
也就是正确答案是:D,程序最终运行出错。
一直调用一直爽,直至栈溢出程序崩溃。
总结
这位大佬出的题目,本质上是比较烦人的,其结合了函数返回参数的命名用法。
如果我们把这个函数的返回参数命名去掉,就可以避开这个问题。如下:
func bbb() (func(), error) {
...
return func() {
print("bbb: surprise!");
done()
}, err
}
...
输出结果为 "bbb: surprise!"。
很多 Go 的同学在日常代码编写的时候不会用到或注意到。但如果写的时候有类似案例代码中的模式,就会排查许久都查不到。
这是个有警惕意义的题目,你觉得呢?
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhhachhc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13