也談Go語言聲明文法

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

一直在從事C語言服務端應用開發,對C的變數聲明文法早已爛熟於胸,同時也深知複雜的C變數聲明十分晦澀難解。記得若干年前還特意花了一些時間研究理解複 雜C變數聲明的方法,記憶中這些方法包括:《C專家編程》中提到的“優先順序”規則、right-left規則以及順時針/螺旋形規則等,幸運地是我們日常 開發中少有使用極為複雜的變數聲明(如void (*signal (int signo, void (*func) (int)))(int);),但C語言中這一痛點卻是事實存在的。

對於我這樣的習慣了C變數聲明文法的程式員來說,Go的變數聲明文法顯得極端另類,完全與C語言反其道而行之,心中不由產生一絲厭惡。但隨著對Go學習和 使用的深入,我逐漸發現Go的這種聲明文法在不經意間解決了複雜聲明的理解問題,你無需學習什麼"優先順序"規則,也無需理會什麼“right-left” 規則,你只需按從左至右的順序閱讀代碼,再複雜的變數聲明也可以很輕易地理解。

Go語言為何要採用這種倒序文法呢?Go的設計者Rob Pike的一篇介紹Go聲明文法的文章給出了答案,其中談到了Go聲明文法的設計考量。Go的設計者從C體系之外的語言獲得啟發:將變數名放在簽名,類型說明放在後 面。這樣更接近於自然語言,例如:

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

在此基礎上,Go的設計者用*、[]等符號替換掉上面的冒號和部分關鍵字使得聲明變得短小,也就形成了Go的聲明文法:

var x int
var p *int
var a [3]int
var b []int

我們只需從左向右的順序閱讀代碼,即可清晰的理解聲明的含義,而不需要像C聲明文法那樣左右符號都要兼顧,螺旋理解。這裡面的*、[n]和[]的含義如下:

*some_type:讀作 pointer to some_type
[n]some_type: 讀作 array[n] of some_type
[]some_type: 讀作 slice of some_type

下面我們通過Go與C的對比來進一步理解Go的聲明文法。

簡單變數聲明

                                           Golang
int x;      <–>      var x int //x has the type int
float x;    <–>      var x float64 //x has the type float64
char c;     <–>      var c byte //x has the type byte

指標變數聲明

C                                            Golang
int *x;     <–>      var x *int //x is a pointer to int
int **p;    <–>      var p **int //p is a pointer to pointer to int 

數組/切片變數聲明

C                                            Golang
int a[5];     <-->    var a [5]int //a is an array[5] of int
int a[5][3];  <-->    var a [5][3]int  //a is an array[5] of array[3] of int
                                            var s []int //s is a slice of int(C語言中無slice類型)

函數類型變數聲明

C                                            Golang
int (*x)(int, int) 類似於   var x func(int, int) int // x has the type "func(int, int) int"
     

Go中函數為first-class類型,其類型的變數等同於C中的函數指標。

複合聲明(複雜聲明)

C                                            Golang
int *x[5];   <-->       var x [5]*int //x is an array[5] of pointer to int
int (*x[5])(int, int)   類似於  var x [5]func(int, int) int // x is an array[5] of "func(int, int) int" 

                                                var f func(func(int,int) int, int) func(int, int) int //f has the type "func(func(int,int) int, int) func(int, int) int",這是一個函數類型變數,這個函數類型接收三個參數(其中一個參數是func(int, int)函數類型),並返回另外一個函數類型(func(int, int) int)。

void (*signal (int signo, void (*Afunc) (int))) 類似於  var signal func(signo int, Afunc func(int))

有了上面的例子,signal就無需再作解釋了,Go的聲明文法可以讓我們可以很容易的理解複雜的變數聲明。但從可讀性角度來看較長的聲明依舊不利於代碼理解。因此我們還是應該通過type定義一些新類型的方式盡量縮短變數聲明的長度,例如:

type Handler func(int)
type SignalHandler func(signo int, handler Handler)
var signal SignalHandler

2012, bigwhite. 著作權.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.