Go語言學之表達式
保留的關鍵字
Go語言僅有25個保留的關鍵字,下面我們就列舉下這25個關鍵字
break | default | func | interface | select |
---|---|---|---|---|
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
流控制
Go語言精簡了控制語句,不在提供while循環與do…while()循環均由for循環代替。
if…else…語句
package main
import(
"fmt"
)
func main(){
x := 3 //爲變量賦值
if x > 5{ //注意此大括號的位置不可以另起一行
fmt.Println("x > 5")
}else if x < 5 && x > 0{ //注意此處的else if也不能另起一行
fmt.Println(x)
}else{
fmt.Println("err")
}
}
輸出: 3
注:以上添加註釋的關鍵點大括號的位置,Go語言中省略了判斷表達式中的”()”但是並不能省略“{}”這一點是需要注意的。比較特別的是對初始化語句的支持,可定義塊局部變量或執行初始化函數
func main(){
x := 3
if init();x == 0{ //先執行init()函數
fmt.Println("a")
}
if i,j := x+1,x+2;i < j{ //定義一個或多個局部變量
fmt.Println("i < j")
}else{
fmt.Println("b")
}
}
使用if…else的一些注意事項
1. 儘可能的減少代碼塊嵌套
2. 對於某些過於複雜的組合條件,建議將其重構爲函數
switch語句
與if類似,switch語句也用於選擇執行
package main
import(
"fmt"
)
func main(){
a,b,c,x := 1,2,3,2
switch x{ //將x與case條件匹配
case a,b: // 多個匹配條件
fmt.Println("a | b")
case c: //單個匹配條件
fmt.Println("c")
case 4: //匹配常量
fmt.Println("d")
default:
fmt.Println("None")
}
}
輸出:a | b
switch語句同樣支持初始化語句,按順序匹配只有全部匹配失敗時纔會執行default塊。
package main
import(
"fmt"
)
func main(){
switch x := 5;x{ //定義並初始化x後進行case匹配
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
case 5:
fmt.Println("5")
default:
fmt.Println("None")
}
}
寫到這好多的C++程序員都會想到爲什麼沒有break,因爲在Go語言中無需顯示執行break,case執行完畢後自動中斷,如需執行後面的case語句需要執行fallthrough,但不在匹配後續條件表達式。
package main
import(
"fmt"
)
func main(){
switch x := 5;x{
case 5:
x += 10
fmt.Println(x)
fallthrough //繼續執行下一個case語句但是不再匹配條件表達式
case 6:
x += 20
fmt.Println(x)
default:
fmt.Println("None")
}
}
輸出:
15
35
注:
1. 相鄰的空case不構成多條件匹配
2. 不能出現重複的case常量值
3. fallthrough必須放在case塊結尾,可使用break語句阻止
for語句
在Go語言中僅有for一種循環語句。
for i := 0;i < 10;i++{ //初始化表達式,同C++中的for(int i = 0; i < 10;i++)
}
for i < 10{ //同C++中的while(i < 10){i++}
i++
}
for{ //同C++中的while(1){}
break
}
初始化語句僅被執行一次。條件表達式中如有函數調用,須確認是否會被重複執行。
package main
import(
"fmt"
)
func count()int{
fmt.Print("count.")
return 3
}
func main(){
for i,c := 0,count();i < c;i++{ //初始化的count函數僅執行一次
fmt.Println("a",i)
}
c := 0
for c < count(){ //條件表達式中的count函數重複執行
fmt.Println("b",c)
c++
}
}
輸出:
count.a 0
a 1
a 2
count.b 0
count.b 1
count.b 2
規避的方法就是在初始化表達式中定義局部變量保存count結果
for…range語句
可用for…range語句完成數據迭代,支持字符串、數組、切片、字典、通道類型,返回索引、鍵值數據。
data type | 1st value | 2nd value |
---|---|---|
string | index | s[index] |
array/slice | index | v[index] |
map | key | value |
channel | element |
package main
import(
"fmt"
)
func main(){
data := [3]string{"a","b","c"}
for i,s := range data{
fmt.Println(i,s)
}
}
輸出:
0 a
1 b
2 c
當然如果不需要索引我們可以使用“_”將其忽略掉
package main
import(
"fmt"
)
func main(){
data := [3]string{"a","b","c"}
for i := range data{ //只返回索引
fmt.Println(i,data[i])
}
for _,s := range data{ //忽略索引,返回值
fmt.Println(s)
}
}
輸出:
0 a
1 b
2 c
a
b
c
無論普通的for循環還是range迭代,其定義的局部變量都會重複使用。
注意:range會複製目標數據。受直接影響的是數組,可改用指針或切片類型。
package main
import(
"fmt"
)
func main(){
data := [3]int{10,20,30}
for i,x := range data{ //從data複製品中取值
if i == 0{
data[0] += 100
data[1] += 200
data[2] += 300
}
fmt.Printf("x: %d,data: %d\n",x,data[i])
}
for i,x := range data[:]{ //僅複製切片,不包括底層數組
if i == 0{
data[0] += 100
data[1] += 200
data[2] += 300
}
fmt.Printf("x: %d,data: %d\n",x,data[i])
}
}
輸出:
x: 10,data: 110
x: 20,data: 220 //range返回的依舊是複製值
x: 30,data: 330
x: 110,data: 210 //當i==0時修改data時,x已經取值所以是110
x: 420,data: 420 //複製的僅是slice自身,底層array仍是院對象
x: 630,data: 630
goto,continue,break語句
goto:被討伐的比較多,在寫C++程序的時候就被告知能不用就不要用goto語句(其實就是告訴你不要用),但是Go語言中保留了goto關鍵字,與在C++中使用的方法相同在使用時需要先定義標籤,標籤區分大小寫。
break:用於switch、for、select語句,終止整個語句塊執行
continue:僅用於for循環,終止當前循環進行下一次循環