日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【译】Go语言声明语法

發布時間:2025/6/17 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【译】Go语言声明语法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

Go語言的初學者可能會好奇為什么Go的類型聲明語法和傳統的C系語言不同。本篇文章我們將比較這兩種不同的類型聲明方式,解釋為什么Go的聲明會是這樣子。

C語法

首先,我們談談C的語法。C采用了一種不同尋常且聰明的類型聲明語法。它沒有使用特殊語法來描述變量類型,而是使用一個包含要聲明變量的表達式,并陳述這個表達式的類型。因此

int x; 復制代碼

聲明x是一個int,因為表達式'X'是int類型。通常,為了弄清楚如何聲明一個新變量,首先得寫一個包含這個變量的表達式,這個表達式本身是一個基礎類型。然后,把這個基礎類型放在左邊,表達式放在右邊。
因此,下面的幾個類型聲明:

int *p; int a[3]; 復制代碼

聲明p是一個int指針,因為表達式”*p“是int類型。而a是一個int數組,因為a[3](忽略其中的數字,這個數字是用來指定數組的大小的)表達式是int類型。
再來看看函數。最開始,C的函數聲明將參數的類型寫在小括號外,像這樣:

int main(argc, argv)int argc;char *argv[]; { /* ... */ } 復制代碼

同樣的,我們看到main是一個函數,因為表達式main(argc, argv)返回一個int。現在的寫法是:

int main(int argc, char *argv[]) { /* ... */ } 復制代碼

但基本結構都是一樣的。
這種語法在類型簡單的時候沒有問題,但在復雜的情況下很容易讓人迷惑。一個著名的例子就是聲明一個函數指針。根據以上規則,應該這么寫:

int (*fp)(int a, int b); 復制代碼

其中,fp是一個函數指針,因為表達式(*fp)(a,b)表示調用一個返回int的函數。那如果fp的某個參數也是一個函數呢?

int (*fp)(int (*ff)(int x, int y), int b) 復制代碼

這就開始變得難以讀懂了。
當然,我們在聲明一個函數時可以去掉參數的名字,所以main可以這樣聲明

int main(int, char *[]) 復制代碼

回憶一下,參數argv的聲明是這樣的,

char *argv[] 復制代碼

所以你從這個聲明語句的中間去掉了變量的名字來構建它的類型。這樣如果你需要聲明一個char *[]的變量,你得把變量名放在char *[]中間,顯然這樣不夠直觀。
如果不聲明參數的名字,來看看fp的聲明會是什么樣?

int (*fp)(int (*)(int, int), int) 復制代碼

這樣不僅不知道變量名該放在哪

int (*)(int, int) 復制代碼

而且很難看出來這是在聲明一個函數指針。進一步,如果該函數的返回類型也是一個函數指針呢?

int (*(*fp)(int (*)(int, int), int))(int, int) 復制代碼

這里甚至很難看出這其中變量名為fp。
這樣精心構建的例子還有很多,這就說明C的變量聲明語法能有多復雜。
還有一點學要提下,就是類型轉換和類型聲明語法是一樣的,這使得C語言很難解析表達式中的類型轉換,這也就是為什么C系語言總是在類型轉換的時候打括號,例如

(int)M_PI 復制代碼

Go語法

非C系語言聲明一個類型聲明的語法通常是很清晰的。首先給出變量名字,然后接一個冒號,后面是類型。那么,上面的例子就變成了這樣(在一個解釋型的函數語言中)

x: int p: pointer to int a: array[3] of int 復制代碼

這些聲明非常清晰,你只需要從左向右讀。Go借鑒了這些,但更簡潔,去掉了冒號和一些關鍵字:

x int p *int a [3]int 復制代碼

[3]int的形式和如何在表達式中使用變量a沒有什么直接的聯系。通過這種分開的語法,表達的更清楚。
再看看函數。將上面的main函數使用Go表達出來(Go中main是沒有參數的):

func main(argc int, argv []string) int 復制代碼

表面上看起來似乎和C沒有多大差別,僅僅把char改成了strings。但Go版本更加適合從左向右閱讀:
main函數接受一個int和一個strings的切片,返回一個int。
去掉參數名也一樣簡潔,因為變量名永遠在聲明的最前面,所以這不會造成迷惑。

func main(int, []string) int 復制代碼

這種從左到右的聲明語法有一個非常實用的地方:當類型非常復雜的時候,它也能很清晰。下面是一個函數變量的聲明(類比C中的函數指針):

f func (func(int, int) int, int) int 復制代碼

或者返回值也是一個函數

f func(func(int, int) int, int) func(int, int) int 復制代碼

從左到右讀起來依然非常清晰,變量的名字也非常明顯,因為它總是第一次出現。
類型轉換和表達式之間的語法區別使得寫和調用閉包都非常容易:

sum := func(a, b int) int { return a+b } (3,4) 復制代碼

指針

指針是規則中的一個特例。普通的,比如數組和切片,Go的類型聲明把中括號放在類型的左邊,但在表達式中會放在類型的右邊:

var a []int x = a[1] 復制代碼

為了使用者更加熟悉,Go的指針也使用了C中*概念,但這就沒有了上面的顛倒規則,因此使用指針是這樣的:

var p *int x = *p 復制代碼

而不是這樣的

var p *int x = p* 復制代碼

因為后綴*與乘法沖突。我們也曾使用過^這個符合,例如:

var p ^int x = p^ 復制代碼

或許我們應該這么寫(使用其他的符號表示異或),因為在類型聲明和表達式中同時使用前綴*在一些情況下會很復雜。例如

[]int("hi") 復制代碼

為了類型轉換,如果類型以*開頭就必須加括號:

(*int)(nil) 復制代碼

如果不使用*作為指針語法,那就不用打括號了。
所以Go的指針嘗試接近C的形式,這就意味著不能完全去掉區分類型聲明和表達式的括號。 總的來說,我們相信Go的類型聲明語法比C更容易理解,特別是在復雜的情況下。

總結

Go的類型聲明語法是從左到右的,而C的類型聲明語法則是螺旋形的!具體參考David Anderson的這篇文章 The "Clockwise/Spiral Rule"

個人總結

Go語言類型聲明語法中,永遠將變量名放在最前面,這比C系語言更加清晰,更適合從左向右閱讀。
但是類型轉換似乎沒有多大區別,都需要括號,只是括號的對象不同而已:

C: (type_name) expression; Go: type_name(expression) 復制代碼

原文

Go's Declaration Syntax

總結

以上是生活随笔為你收集整理的【译】Go语言声明语法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。