Golang 语言该用命名返回值吗?

开发 后端
Golang 语言支持命名返回值,它与使用普通(匿名)返回值不同的是,命名返回值会被视为定义在函数顶部的变量,并且在使用 return 语句返回时,不再必须在其后面指定参数名,也就是支持“裸”返回。

 [[441144]]

01介绍

Golang 语言支持命名返回值,它与使用普通(匿名)返回值不同的是,命名返回值会被视为定义在函数顶部的变量,并且在使用 return 语句返回时,不再必须在其后面指定参数名,也就是支持“裸”返回。

而使用普通返回值时,使用 return 语句返回时,需要在其后面指定与普通返回值相同类型的参数名。

实际上,命名返回值和普通返回值都有其适用的场景,本文我们介绍 Golang 语言函数或方法使用命名返回值和普通返回值各自的“好处”与“坏处”。

02命名返回值

使用命名返回值的“好处”是可以提升代码可读性,读者朋友们试想一下,当函数或方法有多个返回值时,尤其是函数体中代码比较长的函数或方法,如果我们使用普通返回值,那么我们想要知道返回值的含义,就需要先阅读函数体中完整代码。

而如果使用具有实际含义的命名返回值,我们只需要阅读函数或方法的签名,就可以知道其含义,甚至可以把它们作为文档使用。

但是,命名返回值也不是没有“坏处”,如果函数体内有变量与命名返回值同名,那么命名返回值会被覆盖,所以我们也需要注意避免“踩坑”。

03普通返回值

普通(匿名)返回值的“好处”是简洁,当我们写一些简短函数或方法时,使用普通返回值可以使代码更加简洁,在 Golang 语言官方标准库中,有很多使用普通返回值的函数或方法。

但是如果返回值是指针类型时,使用普通返回值,就会使我们函数体中的代码变得不优雅,比如以下这段示例代码。

  1. func c() *int { 
  2.  i := 0 
  3.  return &i 
  4.  
  5. func d() (i *int) { 
  6.  return 

当然这里列举的代码片段是个极端示例,我们在编写 Golang 代码时,也并不会这么使用。

还有就是在编写函数体代码比较长的函数时,使用普通返回值的代码,其可读性比不上使用命名返回值的代码。

04踩坑

defer 在命名返回值和普通返回值的函数或方法中,返回的结果不一样。

  1. func main() { 
  2.  f := fmt.Println 
  3.  f(a()) 
  4.  f(b()) 
  5.  
  6. func a() int { 
  7.  i := 0 
  8.  defer func() { 
  9.   i += 1 
  10.   fmt.Println("a defer:", i) 
  11.  }() 
  12.  return i 
  13.  
  14. func b() (i int) { 
  15.  i = 0 
  16.  defer func() { 
  17.   i += 1 
  18.   fmt.Println("b defer:", i) 
  19.  }() 
  20.  return i 

输出结果:

  1. a defer: 1 
  2. b defer: 1 

阅读上面这段代码,我们可以发现使用普通返回值的函数 a(),返回结果是 0。使用命名返回值的函数 b(),返回结果是 1。

我们在之前的文章中,也单独介绍过 defer 。在这里我们简述一下,当我们使用 defer 调用一个函数时,该函数的执行,被推迟到周围函数返回的那一刻,要么是因为周围的函数执行了 return 语句,要么是因为相应的 goroutine 崩溃。

在函数 a() 中,因为我们没有使用命名返回值,所以返回结果 return i,其中 i 是一个静态值,即使我们在 defer 调用的函数中给变量 i 执行 +1 操作,返回结果中的变量 i 是不可访问的,所以也不会修改返回结果中的变量 i。

在函数 b() 中,因为我们使用命名返回值,所以变量 i 已被分配,并且被初始化为类型零值。即使 defer 调用的函数在返回结果之后执行,返回结果中的变量 i 仍然是可以被访问的,所以其值仍然可以被修改。

05总结

在非简短函数或方法的代码中,建议优先使用命名返回值。它不仅可以提升代码的可读性,也可以帮我们避免一些 “踩坑”。

责任编辑:武晓燕 来源: Golang语言开发栈
相关推荐

2010-07-20 11:37:00

Perl函数返回值

2021-08-13 11:31:23

HTTP

2009-12-07 11:11:41

WCF返回值

2010-07-21 10:32:05

Perl函数返回值

2009-12-25 17:21:13

ADO返回值

2010-07-09 13:20:37

HART协议

2010-03-02 16:50:34

WCF返回值

2022-02-23 13:31:26

RVO编译器优化

2023-08-07 14:52:33

WindowsExplorer进程

2009-11-17 16:16:59

PHP递归函数

2009-09-07 03:07:11

C# Main方法

2009-12-08 15:52:10

WCF回调

2022-01-17 06:58:35

C语言函数错误码

2009-12-23 10:34:15

ADO.NET 批处理

2021-08-06 14:35:26

鸿蒙HarmonyOS应用

2022-09-26 00:00:01

Go语言函数

2010-03-17 17:37:17

Java线程返回值

2022-07-06 07:08:58

CPythonPython返回值

2011-07-19 17:33:53

存储过程javaibatis

2024-01-24 11:35:28

C++多返回值开发
点赞
收藏

51CTO技术栈公众号