Go 函式的多回傳值與具名回傳值

型別後置的寫法讓函式簽章多了兩個特色:連續同型別的參數可以合併寫,以及回傳值可以有多個、甚至可以取名字

參數簡寫

func add(x int, y int) int {}   // 完整寫法
func add(x, y int) int {}       // 連續同型別可以只寫最後一個

多回傳值

func swap(x, y string) (string, string) {
    return y, x
}
 
a, b := swap("hello", "world")   // world hello

多回傳值是 Go 的招牌:v, ok := m[k]v, err := f() 都是它,所以 Go 不需要 exception 也不需要 tuple 型別。

具名回傳值與 naked return

回傳值可以先取名字,等於在函式頂部宣告了這些變數,之後 return 後面什麼都不寫(naked return)就會把它們回傳出去:

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

⚠️ 會降低可讀性:讀到 return 那一行時看不出回傳了什麼,得往回找變數的最後一次賦值。函式一長就很容易誤讀,所以慣例是只在短函式裡用

具名回傳值真正有價值的場合是搭配 defer 修改回傳值(例如在 defer 裡包裝 error),那時名字是必要的——除此之外,把回傳值寫清楚在 return 後面通常更好。

相關:Go 宣告變數的四種寫法defer 是後進先出,登記時機在執行到那一行