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循环,终止当前循环进行下一次循环