為什么 Go 不支持函數重載和缺省參數?
文末本文轉載自微信公眾號「腦子進煎魚了」,作者 陳煎魚 。轉載本文請聯系腦子進煎魚了公眾號。
大家好,我是煎魚。
部分同學在初學習 Go 語言時,帶著其他語言的習慣,總是會有些不習慣,感覺非常不能理解,直打問號。
其中一點就是問到 “為什么 Go 語言不支持函數重載和缺省參數”,覺得使用起來很不方便,畢竟以前能省了定義不少東西。
為此,在這篇文章中煎魚就和大家一起來了解為什么,有又會怎么樣。
函數重載
函數重載(function overloading),也叫方法重載。是某些編程語言(如 C++、C#、Java、Swift、Kotlin 等)具有的一項特性。
該特性允許創建多個具有不同實現的同名函數,對重載函數的調用會運行其適用于調用上下文的具體實現。
從功能上來講,就是允許一個函數調用根據上下文執行不同的方法,達到調用同一個函數名,執行不同的方法。
一個簡單的例子:
- #include <iostream>
- int Volume(int s) { // 立方體的體積。
- return s * s * s;
- }
- double Volume(double r, int h) { // 圓柱體的體積。
- return 3.1415926 * r * r * static_cast<double>(h);
- }
- long Volume(long l, int b, int h) { // 長方體的體積。
- return l * b * h;
- }
- int main() {
- std::cout << Volume(10);
- std::cout << Volume(2.5, 8);
- std::cout << Volume(100l, 75, 15);
- }
在上述例子中,實現了 3 個同名的 Volume 函數,但是 3 個函數的入參個數、類型均不一樣,也代表了不同的實現目的。
在主函數 main 中,傳入了不同的入參,編譯器或運行時再進行內部處理,從程序上來看達到了調用不同函數的目的。
這就是函數重載,一函數多形態。
參數默認值
參數默認值,又叫缺省參數。指的是允許程序員設定缺省參數并指定默認值,當調用該函數并未指定值時,該缺省參數將為缺省值來使用。
一個簡單的例子:
- int my_func(int a, int b, int c=12);
在上述例子中,函數 my_func 一共有 3 個變量,分別是:a、b、c。變量 c 設置了缺省值,也就是 12。
其調用方式可以為:
- // 第一種調用方式
- result = my_func(1, 2, 3);
- // 第二種調用方式
- result = my_func(1, 2);
在第一種方式中,就會正常的傳入所有參數。在第二種方式,由于第三個參數 c 并沒有傳遞,因此會直接使用缺省值 12。
這就是參數默認值,也叫缺省參數。
為什么不支持
美好
從上述的功能特性介紹來看,似乎非常的不錯,能夠節省很多功夫。像是 Go 語言的 context 庫中的這些方法:
- func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
- func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
- func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
要是有函數重載,直接就 WithXXX 就好了,只需要關注傳入的參數類型,也不用 “記” 那么多個方法名了。
有同學說,有參數默認值。那就可以直接設置在上面,作為 “最佳實踐” 給到使用函數的人,豈不美哉。那怎么 Go 語言就不支持呢?
細思
其實這和設計理念,和對程序的理解有關系。說白了,就是你喜歡 “顯式”,還是 “隱喻”。
函數重載和參數默認值,其實是不好的行為。調用者只看函數名字,可能沒法知道,你這個默認值,又或是入參不同,會調用的東西,會產生怎么樣的后果?
你可以觀察一下自己的行為。大部分人都會潛意識的追進去看代碼,看看會調到哪,缺省值的作用是什么,以確保可控。
敲定
這細思的可能,在 Go 語言中是不被允許的。Go 語言的設計理念就是 “顯式大于隱喻”,追求明確,顯式。
在 Go FAQ 《Why does Go not support overloading of methods and operators?》有相關的解釋。
如下圖:
官方有明確提到兩個觀點:
- 函數重載:擁有各種同名但不同簽名的方法有時是很有用的,但在實踐中也可能是混亂和脆弱的。
- 參數默認值:操作符重載,似乎更像是一種便利,不是絕對的要求。沒有它,程序會更簡單。
這就是為什么 Go 語言不支持的原因。
總結
在這篇文章中,我們介紹了業內常見的編程語言的函數重載和參數默認值的概念和使用方法。也結合了 Go 語言自身的設計理念,說明了為什么不支持的原因。
你會希望 Go 語言支持這幾個特性功能嗎,歡迎在評論區留言討論和交流:)
參考
維基百科(函數重載和缺省值定義)
Frequently Asked Questions (FAQ)