go——基本構成要素
Go的語言符號又稱為詞法元素,共包括5類內容:
識別符號(identifier)
關鍵字(keyword)
字面量(literal)
分隔符(delimiter)
操作符(operator)
它們可以組成各種表示式和語句,而後者都無需以分號結尾。
1.識別符號
識別符號可以表示程式實體,前者即為後者的名稱。
在一般情況下,同一個程式碼塊中不允許出現同名的程式主體。
在Go中,變數、常量、函式和型別宣告可統稱為程式實體,而它們的名稱統稱為識別符號。
識別符號可以是Unicode字符集中任意能表示自然語言文字的字元、數字以及下劃線(_)。識別符號不能以數字或下劃線開頭。
實際上,識別符號的首字元的大小寫控制著對應程式實體的訪問許可權。
如果識別符號的首字元是大寫形式,那麼它所對應的程式實體就可以被本程式碼之外的程式碼訪問到,也稱之為可匯出或公開的;
否則,對應的程式實體就只能被本包內的程式碼訪問,也成為不可匯出的或包私有的。
要想成為可匯出的程式實體,還需要額外滿足以下兩個條件。
a.程式實體必須是非區域性的。區域性的程式實體是指:它被定義在了函式或結構體的內部。
b.程式碼包所屬目錄必須包含在GOPATH中定義的工作區目錄中。
使用不同程式碼包中的程式實體需要用到限定的識別符號。比如:os.O_RDONLY。
另外,Go中還存在著一類特殊的識別符號,叫做預定義識別符號,它們是在Go原始碼中宣告的。
這類識別符號包括以下幾種:
a.所有基本資料型別的名稱。
b.介面型別error。
c.常量true、false和iota。
所有內建函式的名稱,即append、cap、close、complex、copy、delete、
imag、len、make、new、panic、print、println、real和recover。
這裡強調一下空識別符號,它由一個下劃線_表示,一般用在變數宣告或程式碼包匯入語句中。
若在程式碼中存在一個變數x,但是卻不存在任何對它的使用,則編譯器會報錯。
如果在變數x的宣告程式碼後新增這樣一行程式碼:
_ =x
就可以繞過編譯器的檢查,使它不產生任何編譯錯誤。
這是因為這段程式碼確實用到了變數x,只不過它沒有在變數x上進行任何操作,也沒有將它賦值給任何其他變數。
空識別符號就像一個垃圾桶。在相關初始化工作完成之後,操作物件就會被棄之不用。
2.關鍵字
關鍵字是被程式語言保留的字元序列,程式設計人員不能把他們用作識別符號。因此,關鍵字也稱為保留字。
Go的關鍵字可以分為3類,包括用於程式宣告的關鍵字、用於實體宣告和定義的關鍵字,以及用於程式流程的關鍵字。
Go的關鍵字自共有25個,其中與併發程式設計有關的關鍵字有go、chan和select。
需要說明一下的是關鍵字type——型別宣告。我們可以使用它宣告一個自定義型別:
type myString string
這裡把名為myString的型別宣告為string型別的一個別名型別。
反過來說,string型別是myString型別的潛在型別。
雖然型別及其潛在型別是不同的兩個型別,但是它們的值可以進行型別轉換,而且不會產生新值也沒有什麼代價。
自定義的型別一般都會基於Go中的一個或多個預定義型別。
如果為自定義型別關聯若干辦法(函式的變體),那麼還可以讓它成為某個或某些介面型別的實現型別。
另外,還有一個比較特殊的型別,叫做空介面。它的型別字面量是interface{}。在Go語言中,任何型別都是空介面型別的實現型別。
3.字面量
簡單來說,字面量就是值的一種標記法。但是,在Go中,字面量的含義要更加廣泛一些。
我們常常用到的字面量有以下三類:
(1)用於表示基礎資料型別值的各種字面量。例如:表示浮點數型別值的12E-3.
(2)用於構造各種自定義的複合資料型別的型別自變數。例如下面的字面量定義了一個名稱為Name的結構型別。
type Name struct { Forename string Surname string }
(3)用於表示複合資料型別的值的複合字面量,它可以是用來構造struct(結構體)、array(陣列)、slice(切片)和map(字典)型別的值。
複合字面量一般由字面型別以及被花括號包裹的複合元素的列表組成。
字面型別指的是複合資料型別的名稱。例如:複合字面量構造出一個Name型別的值。
Name{Forename:"Rebert",Surname:"Hao"}
其中Name表示這個值的型別,緊隨其後的就是由鍵值對錶示的複合元素列表。
4.操作符
操作符,也成為運算子。它是用於執行特定算術或邏輯操作的符號,操作的物件稱為運算元。
點選這裡 | 點選這裡 | 點選這裡 |
---|---|---|
符號 | 說明 | 示例 |
|| | 邏輯或,二元操作符,也是邏輯操作符 | true||fale //true |
&& | 邏輯與,二元操作符,也是邏輯操作符 | true&&false //flase |
== | 相等,二元操作符,也是比較操作符 | "abc"=="abc" //true |
!= | 不相等,二元操作符,也是比較操作符 | “abc”!="Abc" //true |
< | 小於,二元操作符,也是比較操作符 | 1 < 2 //true |
<= | 小於或等於,二元操作符,也是比較操作符 | 1 <= 2 //true |
> | 大於,二元操作符,也是比較操作符 | 3 > 2 //true |
>= | 大於或等於,二元操作符,也是比較操作符 | 3 >= 2 //true |
+ | 求和,既是一元操作符也是二元操作符,也屬於算術操作符,若是一元操作符不會對原值產生任何影響 | 1 + 2 //3 |
- | 求差,既是一元操作符也是二元操作符,也屬於算術操作符,若是一元操作符,則表示求反操作 | 1 - 2 // -1 |
| | 按位或操作,它是二元操作符,同時也屬於算術操作符 | 5 | 11 //15 |
^ | 按位異或操作,既是一元操作符也是二元操作符,若是一元操作符表示按位補碼操作,也屬於算數操作符 | 5 ^ 11 //14 |
* | 求乘積操作,既是一元操作符也是二元操作符,也屬於算術操作符和地址操作符,若為地址操作符則表示取值操作 | *p //若p為指向整數型別值為2的指標型別,則結果為2 |
/ | 求商操作,二元操作符,也屬於算術操作符 | 10 / 5 //2 |
% | 求餘數操作,二元操作符,也屬於算術操作符 | 12 % 5 //2 |
<< | 按位左移操作,二元操作符,也屬於算術操作符 | 4 << 2 //16 |
>> | 按位右移操作,二元操作符,也屬於算術操作符 | 4 >> 2 //1 |
& | 按位與,既是一元操作符也是二元操作符,,同時也屬於算術操作符和地址操作符,若為地址操作符,表示取值操作 | &v //識別符號v所代表的值在記憶體中的地址 |
&^ | 按位清除操作,二元操作符,也屬於算術操作符 | 5 &^ 11 //4 |
! | 邏輯非,一元操作符,也屬於邏輯操作符 | !b //如果b為false,則結果為true |
<- | 接收操作,一元操作符,也屬於接收操作符 | <- ch //接收一個byte型別值 |
Go的操作符一共由21個,並分為了5類:算術操作符、比較操作符、邏輯操作符、地址操作符和接收操作符。
當一個表示式中存在多個操作符的時候,就涉及操作順序的問題。
在Go中,一元操作符擁有最高的優先順序,二元操作符的優先順序如下表所示:
數字越大意味著優先順序就越高,如果一個表示式中出現了處於相同優先順序的多個操作符,
且這些操作符之間僅存在運算元,那麼就會按照從左到右的順序進行操作。
當然可以使用圓括號顯式改變原有的操作順序,例如表示式a << (4 * b) & c,
表示式雖然操作符的優先順序一樣,但是4 * b會先被求值。
需要注意的是,++和--是語句而不是表示式,因而它們不存在於任何操作符優先順序層次之內。例如(*p)--等於*p--。
5.表示式
表示式是把操作符和函式作用於運算元的計算方法。
在Go中,表示式是構成具有詞法意義的程式碼的最基本元素。
關於型別斷言,有兩點需要注意:
(1)如果v1是一個非介面值,那麼必須在做型別斷言之前把它轉換成介面值。
因為Go中的任何型別都是空介面型別的實現型別,所以一般會這樣:interface{}(v1).(I1).
(2)如果型別斷言的結果為否,就意味著該型別斷言是失敗的。失敗的;
失敗的型別會引發異常,解決方法是:
var i1,ok = interface{}(v1).(I1)
這裡宣告並賦值了兩個變數,其中ok是布林型別的變數,它的值體現了型別判斷的成敗。
如果成功,i1就會是經過型別轉換後的I1型別的值,否則它將會是I1型別的零值(或預設值)。
如此一來,當型別斷言失敗時,執行異常也就不會發生。
關鍵字var用於變數的宣告。在它和等號=之間可以由多個逗號隔開的變數名。
這種在一條語句中同時為多個變數賦值的方式叫做平行賦值。
另外,如果在宣告變數的同時進行賦值,那麼等號左邊的變數型別可以省略
var i1 I1 var ok bool i1,ok = interface{}(v1).(I1)
另一方面,上面那條語句還可以簡寫成:
i1,ok :=interface{}(v1)(I1)
這種簡寫方式只能出現在函式中。有了符號:=,關鍵字var就可以省略,這叫做短變數宣告。