爲什麼 Go 語言把類型放在後面?

大家好,我是煎魚。

前段時間看到大家在吵一個話題,那就是 Go 語言的類型聲明,摳知識摳的非常細了,就是爲什麼他要放在後面,展開了熱烈的討論。

示例代碼如下:

var a []string
var b []string

其實在早年 Go 官方估計已經被問煩了,寫過一篇《Go's Declaration Syntax[1]》來具體介紹和說明情況。

爲此煎魚將參考並結合這篇官方資料,帶大家一起了解爲什麼 Go 如此的 “與衆不同” ,爲什麼要把類型放在後面。

類型前置

在業內目前有不少知名語言,也採取的是在聲明變量類型時,把類型定義在名字前面。像是 C、C++、C#、Java 等:

int x;
int x = 100;

基本的格式定義:<data_type> <variable_list>;。

上面的聲明是一個簡單的例子,如果更復雜一些,Go 官方還給出了著名的函數指針的例子:

int (*fp)(int a, int b);

更進一步,如果返回值也是個函數指針類型,就會變成:

int (*(*fp)(int (*)(int, int), int))(int, int)

這已經很難看出來是個 fp 的聲明瞭。

類型後置

前面所舉例的類型前置的編程語言,很多都是 C 系列中的一者。類型後置的代表,分別有:Go、Rust、Scala、Kotlin 等。

其實在很多類型後置的編程語言種,會採取變量名 + 冒號 + 類型的方式出現。就像 Rust 一樣:

let x: i32;

基本的格式定義:

x: int
p: pointer to int
a: array[3] of int

Go 官方參照了這類類型後置的設計,並且爲了簡潔,進一步去掉了冒號和一些關鍵字,變成:

var a []string

我們再看回前面 fp 的聲明的例子:

int (*(*fp)(int (*)(int, int), int))(int, int)

再對比 Go 語言中就變成了:

f func(func(int,int) int, int) func(int, int) int

兩者一對比,Go 語言代碼可讀性確實更高一些。

思考

後置類別

在類型聲明上,實際上分爲:變量類型後置、函數返回值後置。兩者共同構建了前置還是後置,總不能一個前置,一個後置吧,那得多麼的難受。

上方 C 語言和 Go 語言函數指針的例子,所對比帶來的代碼可讀性提高,其實本質上是由函數返回值後置所帶來的。

和類型前置、後置沒太多直接關係。

核心思想

在類型後置上來講,Go 官方核心思想是:這種聲明方式(從左到右的風格)的一個優點是,當類型變得更加複雜時,它的效果非常好(One merit of this left-to-right style is how well it works as the types become more complex)。

Go 的變量名總是在前,在人的代碼閱讀上可以保持從左到右閱讀,不需要像 C 語言一樣在一大堆聲明中用技巧找變量名對應的類型。

The Clockwise/Spiral Rule

爲此甚至有人寫了篇 C 語言的順時針讀法《The Clockwise/Spiral Rule[2]》,有興趣可以閱讀。

如此一對比,Go 語言的類型後置在複雜場景下與 C 語言的對比確實更好一些。

其他因素

類型推導

諸如在類型推導的形式上也會更直觀:

func main() {
    var s1 := "腦子進煎魚了"
    var s2 string
}

也是一個可讀性提高的問題。

類型和名字誰更重要

不同設計者對誰更重要的理解也不一樣。是類型更重要,還是名字更重要呢?

有的人認爲是類型,有的人認爲是名字。這就真的是千人千面,衆口難調了。

C# 的後悔

我們看看其他語言,C# 設計組成員之一,其實在《Sharp Regrets: Top 10 Worst C# Features[3]》中的第五點表達了個人對類型前置、後置的設計教訓。

核心觀點是:從編程和數學兩方面來看,都有一個約定,即計算的結果在右側表示,所以在類 C 語言中,類型在左側是很奇怪的。

在設計時,C# 本來計劃把類型註釋放在右邊。但考慮到類 C 語言,因此遵循了其他語言的慣例。

總結

實際上該問題的研討,在 2021 年的現在,大部分 case 都一一被反駁了。類型後置也不是一個與衆不同的設計,很多語言都是如此。但既然要討論 Go 語言,那更多的是站在設計者的角度去考慮

結合 Go 所提供的官方資料,在當年的目的更多的是爲了在遇到複雜類型定義時,能保持一定的代碼可讀性

當然,這不可否認肯定包含 Go 開發團隊的主觀意識。有興趣的可以具體挖挖背後的信息。

如果是你,你會希望類型放在前面,還是後面呢,爲什****麼?

參考資料

[1]

Go's Declaration Syntax: https://go.dev/blog/declaration-syntax

[2]

The Clockwise/Spiral Rule: http://c-faq.com/decl/spiral.anderson.html

[3]

Sharp Regrets: Top 10 Worst C# Features: https://www.informit.com/articles/article.aspx?p=2425867

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/t3vEQXg1yfDUz1spRmTieQ