大家好,我是煎魚。
在前兩週我們在這篇《你能答對這道 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) {
帶有三個明確的特徵:
- Go 函式的返回或結果 "引數 "可以被命名並作為常規變數使用,就像傳入引數一樣。
- 當命名時,它們在函式開始時被初始化為其型別的零值。
- 如果函式執行沒有引數的返回語句,結果引數的當前值被用作返回值。
簡單來講,就是和常規入參一樣,宣告後會自帶零值,如果 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 的風格,就是顯式命名了返回。
但也會帶來可能存在的函式內返回的省略,以至於很多人新入門的朋友看不懂。又或是像是開頭文章內所介紹的,帶命名的返回引數寫著寫著變成遞迴函式,一手抖也是會出現的。
該特性,建議平時斟酌使用,短小精悍的可以考慮,又長又多的建議還是不要增加過多的繁瑣了。
文章持續更新,可以微信搜【腦子進煎魚了】閱讀,本文 GitHub github.com/eddycjy/blog 已收錄,學習 Go 語言可以看 Go 學習地圖和路線,歡迎 Star 催更。