表達式
1. 關鍵字 2. 運算符 3. 初始化
關鍵字
關鍵字是指被編程語言保留而不讓編程人員作爲標誌符使用的字符序列。因此,關鍵字也稱爲保留字, 每種編程語言都有自己的關鍵字,從使用的角度看,我們可以把Go語言的25個關鍵字分爲如下三類:
1. 用於程序聲明 2. 用於程序實體聲明和定義 3. 用於程序流程控制的關鍵字
類別 | 關鍵字 |
---|---|
程序聲明 | import, package |
實體聲明和定義 | var,const,type,struct,func,interface,map,chan |
流程控制 | if,else,switch,case,fallthrough,default,for,range,continue,break,go,select,defer,goto,return |
運算符
運算符就是用於執行特定計算或邏輯操作的符號。 Go語言中全部運算符、分隔符以及其他特殊符號見下表:
+ & += &= && == != ( ) - | -= |= || < <= [ ] * ^ *= ^= <- > >= { } / << /= <<= ++ = := , ; % >> %= >>= -- ! ... . : &^ &^=
運算符分類:
1. 算術運算符 2. 關係運算符 3. 邏輯運算符 4. 位運算符 5. 賦值運算符 6. 其他運算符
算術運算符
下面爲Go語言的算術運算符,假定A值爲10,B值爲20
運算符 | 描述 | 實例 |
---|---|---|
A+B | 加 | A + B 輸出結果 30 |
A-B | 減 | A - B 輸出結果 -10 |
A*B | 乘 | A * B 輸出結果 200 |
A/B | 除 | B / A 輸出結果 2 |
B%A | 求餘 | B % A 輸出結果 0 |
A++ | 自增 | A++ 輸出結果 11 |
A-- | 自減 | A-- 輸出結果 9 |
關係運算符
下面爲Go語言的關係運算符,假定A值爲10,B值爲20:
運算符 | 描述 | 實例 |
---|---|---|
A==B | 檢查兩個值是否相等,如果相等返回 True 否則返回 False | (A == B) 爲 False |
A!=B | 檢查兩個值是否不相等,如果不相等返回 True 否則返回 False | (A != B) 爲 True |
A>B | 檢查左邊值是否大於右邊值,如果是返回 True 否則返回 False | (A > B) 爲 False |
A<B | 檢查左邊值是否小於右邊值,如果是返回 True 否則返回 False | (A < B) 爲 True |
A>=B | 檢查左邊值是否大於等於右邊值,如果是返回 True 否則返回 False | (A >= B) 爲 False |
A<=B | 檢查左邊值是否小於等於右邊值,如果是返回 True 否則返回 False | (A <= B) 爲 True |
邏輯運算符
下表列出了所有Go語言的邏輯運算符。假定 A 值爲 True,B 值爲 False
運算符 | 描述 | 實例 |
---|---|---|
A&&B | 邏輯AND運算符.如果兩邊的操作數都是True,則條件True,否則爲False | (A && B) 爲 False |
A||B | 邏輯OR運算符.如果兩邊的操作數有一個True,則條件True,否則爲False | (A || B) 爲 True |
!(A && B) | 邏輯NOT運算符.如果條件爲True,則邏輯NOT條件False,否則爲True | !(A && B) 爲 True |
位運算符
下表列出了所有Go語言的位運算符。假定 A 值爲 0101,B 值爲 0011,C值爲1,D值爲8
運算符 | 描述 | 實例 |
---|---|---|
A&B | 按位與運算,兩邊都爲1結果就爲1 | 0101 & 0011 = 0001 |
A|B | 按位或運算,兩邊至少有一個爲1結果就爲1 | 0101 | 0011 = 0111 |
A^B | 按位亦或運算,兩邊只有一個爲1結果就爲1 | 0101 | 0011 = 0110 |
^A | 按位取反運算 | ^0111 = 1000 |
A&^B | 按位清除運算 | 0101 &^ 0110 = 0001 |
C<<2 | 位左移運算 | 1<<2 = 4 |
D>>2 | 位右移運算 | 8>>2 = 2 |
賦值運算符
下表列出了所有Go語言的賦值運算符
運算符 | 描述 | 實例 |
---|---|---|
= | 簡單的賦值運算符 | C = A + B 將 A + B 表達式結果賦值給 C |
+= | 相加後再賦值 | C += A 等於 C = C + A |
-= | 相減後再賦值 | C -= A 等於 C = C - A |
*= | 相乘後再賦值 | C = A 等於 C = C A |
/= | 相除後再賦值 | C /= A 等於 C = C / A |
%= | 求餘後再賦值 | C %= A 等於 C = C % A |
<<= | 左移賦值 | C <<= 2 等於 C = C << 2 |
>>= | 右移賦值 | C >>= 2 等於 C = C >> 2 |
&= | 位邏輯與賦值 | C &= 2 等於 C = C & 2 |
|= | 位邏輯或賦值 | C |= 2 等於 C = C |2 |
^= | 位邏輯異或賦值 | C ^= 2 等於 C = C ^ 2 |
其他運算符
下表列出了Go語言的其他運算符
運算符 | 描述 | 實例 |
---|---|---|
& | 取址運算符 | &a 將給出變量a的實際地址 |
* | 指針運算符 | *a 將給出指針變量a所指向的值 |
<- | 接收運算符 | x,ok := <-ch,表示從channel中接收數據 |
:= | 短變量聲明符 | var x = 100可以寫成 x:= 100 |
優先級
當一個表達式中包含多個運算符時,就涉及到了運算符的運算優先級,在Go語言中,一元運算符擁有最高優先級,下表列出了Go語言的 二元運算符優先級,從高到低:
優先級| 運算符 5 | * / % << >> & &^ 4 | + - | ^ 3 | == != < <= > >= 2 | && 1 | ||
另外下面幾點是日常開發中需要注意的:
可以通過使用括號來臨時提升某個表達式的整體運算優先級
位操作
除了位操作外,操作數類型必須相同,如果其中一個是無顯示類型聲明的常量,那麼該常量操作數就會 做自動轉型,比如:
const v = 20 var a byte = 10 b := a + v // v常量被自動轉型爲byte/uint8 類型 const f float32 = 1.2 d := f + v // v常量被自動轉型爲float32 類型
位移右操作數必須是無符號數或可以轉換的無顯示類型常量,比如:
b := 2 x := 1 << b //b 是有符號int類型變量,這樣是無效的
如果是非常量位移表達式,那麼會優先將無顯示類型的常量左操作數轉型,比如:
a := 1.0 << 3 //常量表達式 c := 1.3 << 3 //constant 1.3 truncated to integer var s uint = 3 b := 1.0 << s //invalid operation: 1 << s (shift of type float64) var i int32 = 1.0 << s //自動將1.0 轉換爲int32
自增/自減
不能用於表達式,只能作爲獨立語句,比如:
a := 1 ++a //syntax error: unexpected ++ 不能前置 if (a++) > 1{ //syntax error: unexpected ++ 不能作爲表達式 } a++ p := &a *p++ //*p++相當於(*p)++
指針
不能將指針與內存地址混位一體,內存地址是在內存中每個字節單元的唯一編號,而指針就相當於是用來保存地址的整型變量,自身也會佔用內存空間。 比如上例中的p := &a
a :=1 p := &a fmt.Println(&a,a) fmt.Println(&p,p,*p) 輸出:0x1040e0f8 10x1040a120 0x1040e0f8 1
並不是所有的對象都能進行取址操作,比如:
m := map[string]string{"hello":"go"} println(&m["hello"]) //cannot take the address of m["hello"]
指針類型不能做加減法和類型轉換,支持相等運算符
a := 10 p := &a p++ //invalid operation: p++ (non-numeric type *int) p2 := &a println(p == p2) //支持相等運算符
零長度對象(聲明但未賦值)的對象地址是否相等和具體實現有關,Go編譯器會根據其實現的不同,進行不同的優化, 從正確性的角度看,用戶是不用關心內存在哪裏(堆棧)分配的,不過肯定不爲nil,比如:
var a,b int //雖然長度爲0,但是對象是合法存在的,就擁有合法內存地址,不會爲nil println(&a , &b) println(&a == &b,&a == nil) 輸出: 0x10429f64 0x10429f60 false false var a,b struct{} println(&a , &b) println(&a == &b,&a == nil) 輸出: 0x10429f65 0x10429f65 true false
指針沒有專門指向成員的"->"運算符, 統一使用".",比如:
a := struct{ x int }{} a.x = 10 //相當於a->x p := &a p.x += 10 //相當於p->x println(p.x)
初始化
基本變量的初始化前面已經提到了字面量,在Go語言中,對複合類型變量(數組、切片、字典、結構體) 的初始化是有一些語法限制的,但對基本變量的初始化沒有這些限制,比如:
1. 初始化表達式必須含有類型標籤 2. 左花括號不能另起一行,必須在類型尾部 3. 多成員初始值必須用逗號","分隔 4. 允許多行編寫,但是每行必須以逗號","或右花括號結束
示例如下:
type stu struct{ name string age int } b := stu{ "zhang", 20 //unexpected semicolon or newline, expecting comma or },須以逗號或右花括號結束 } b := stu { //syntax error: unexpected }, expecting expression,左花括號不能另起一行 "zhang", 20, } var data stu = {"wang",20} //syntax error: missing operand,初始化表達式必須含有類型標籤
借鑑: 雨痕<GO學習筆記>
討論微信: 675020908