Go 返回值命名还有存在的必要吗?
2022-3-30 18:12:0 Author: mp.weixin.qq.com(查看原文) 阅读量:40 收藏

大家好,我是煎鱼。

在前两周我们在这篇《你能答对这道 Go 题目吗?超过 80% 的人都答错了...》文章中,针对题目,有小伙伴提出了如下问题:

为此,今天我们就来了解一下 Go 函数的返回值命名的意义是什么?

案例

函数 a 带返回值,函数 b 是不带返回值命名的例子。如下:

func a() (done func()err error) {
 return func() { 
   print("aaa: done"
 }, nil
}

func b() (func()error) {
 return func() { 
   print("aaa: done"
 }, nil
}

这是日常工作中最常见的,前两年年我听到有同学不知道有命名返回值的用法,也不知道函数结尾返回个 return 的意义是什么,这有啥用?

官方解释

在官方的《Effective Go》中,明确将带命名的返回值参数定义为 Named result parameters(命名的结果参数)。

函数签名如下:

func nextInt(b []byte, pos int) (value, nextPos int) {

带有三个明确的特征:

  1. Go 函数的返回或结果 "参数 "可以被命名并作为常规变量使用,就像传入参数一样。
  2. 当命名时,它们在函数开始时被初始化为其类型的零值。
  3. 如果函数执行没有参数的返回语句,结果参数的当前值被用作返回值。

简单来讲,就是和常规入参一样,声明后会自带零值,如果 return 没指定,则会默认返回声明的返回变量。

官方定义的作用是:“可以使代码更短、更清晰”。像是给 nextInt 函数的返回的结果命名,那你就能很明确知道,第一个返回的值是 value,第二个是 nextPos,起到显式声明的作用。

建议

在官网的《A Tour of Go》中明确指出 Named result parameters 只建议在较短的函数中使用。

例如以下例子:

func split(sum int) (x, y int) {
 x = sum * 4 / 9
 y = sum - x
 return
}

func main() {
 fmt.Println(split(17))
}

如果是在较长的函数中使用,它们会损害可读性。也见过因为写的太长了,为了优化可读性,不断换行的代码编写,越搞越繁琐的场景。

总结

实际上带命名的返回参数,比较带有 Go 的风格,就是显式命名了返回。

但也会带来可能存在的函数内返回的省略,以至于很多人新入门的朋友看不懂。又或是像是开头文章内所介绍的,带命名的返回参数写着写着变成递归函数,一手抖也是会出现的。

该特性,建议平时斟酌使用,短小精悍的可以考虑,又长又多的建议还是不要增加过多的繁琐了。

推荐阅读

关注煎鱼,获取业内第一手消息和知识 👇

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxNzY0NDE3NA==&mid=2247489775&idx=2&sn=80bfcfd75154ce2a58f72bd328a934bf&chksm=9be3370eac94be18aa666b2a66ba7473f19caf3a3d1b06fc3d018fd0c184d50789f261b5d6bc#rd
如有侵权请联系:admin#unsafe.sh