当前位置: 首页 > 科技观察

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

时间:2023-03-20 14:02:13 科技观察

01介绍Golang语言支持具名返回值,与使用普通(匿名)返回值不同的是,具名返回值会被当成一个定义在函数顶部的变量,当使用return语句时return,不再需要在其后指定参数名,即支持“裸”返回。使用普通返回值时,使用return语句返回时,需要在其后指定一个与普通返回值相同类型的参数名。其实无论是命名返回值还是普通返回值都有其适用的场景。在本文中,我们分别介绍使用命名返回值和普通返回值的Golang语言函数或方法的“优点”和“缺点”。02命名返回值使用命名返回值的“好处”是可以提高代码的可读性。各位读者,想象一下,当一个函数或方法有多个返回值时,尤其是函数体中代码比较长的函数或方法,如果我们使用普通的返回值,那么我们需要先阅读函数体中的完整代码如果我们想知道返回值的含义。而如果我们使用具有实际意义的命名返回值,我们只需要阅读函数或方法的签名就可以知道它的意义,甚至可以将它们用作文档。然而,命名返回值并非没有“缺点”。如果函数体中存在与命名返回值同名的变量,命名返回值会被覆盖,所以我们也需要注意避免“踩坑”。03普通返回值普通(匿名)返回值的“好处”是简单。当我们编写一些简短的函数或方法时,使用普通的返回值可以使代码更加简洁。在Golang语言的官方标准库中,有很多使用普通的返回值的函数或方法。但是如果返回值是指针类型的话,使用普通的返回值会让我们函数体中的代码显得不够优雅,比如下面的示例代码。funcc()*int{i:=0return&i}funcd()(i*int){return}当然,这里列出的代码片段是一个极端的例子,我们在编写Golang代码时不会使用它。另外,在编写函数体代码比较长的函数时,使用普通返回值的代码可读性不如使用具名返回值的代码。04踩到defer在命名返回值和普通返回值的函数或方法中,返回的结果不同。funcmain(){f:=fmt.Printlnf(a())f(b())}funca()int{i:=0deferfunc(){i+=1fmt.Println("adefer:",i)}()returni}funcb()(iint){i=0deferfunc(){i+=1fmt.Println("bdefer:",i)}()returni}输出结果:adefer:10bdefer:11阅读上面的代码,我们可以发现使用普通返回值的函数a()返回0。使用命名返回值的函数b(),返回结果为1。我们在之前的文章中也单独介绍过defer。这里简单说明一下,当我们使用defer调用一个函数时,这个函数的执行会被推迟到周围函数返回的那一刻,要么是因为周围函数执行了return语句,要么是因为对应的goroutine崩溃了。在函数a()中,由于我们没有使用具名返回值,返回结果为returni,其中i为静态值,即使我们在defer调用的函数中对变量i进行+1操作,返回结果中的变量i是不可访问的,所以返回结果中的变量i不会被修改。在函数b()中,因为我们使用命名返回值,所以变量i已分配并初始化为零类型值。即使defer调用的函数在返回结果后执行,返回结果中的变量i仍然可以访问,所以它的值仍然可以被修改。05总结在非短函数或方法的代码中,建议优先使用命名返回值。既可以提高代码的可读性,又可以帮助我们避免一些“踩坑”。