if条件语句
语法与C++一样,要注意的是:
1.条件不需要用小括号括起来
2.即使只有一条执行语句,也要有大括号,左括号必须与if、else、else if关键字同行
3.if的条件判断语句可以引入声明,声明的对象只在该if语句块中可见(该语句块中的多个if、else分支均可见),声明与条件判断用分号分隔
4.if语句的判断条件必须是布尔值,不能够是其他类型,也即不能像C++那样:非零值为true,零值为false。
if a:=10; a>1{
fmt.Print(a)
} else {
fmt.Print("111")
}
switch语句
基本语法与C++一致,但每个case分支都默认加了break,不需手动添加。如果匹配了一个case后还想继续往下找case匹配,那么需要添加fallthrough关键字。(在break逻辑上刚好与C++相反的除了方式)
由于Go会给每个分支默认加上break,本质上只要没有指定fallthrough,执行完一个分支后switch语句块就结束了,所以在分支中显式的写出break和不写是没有区别的,switch语句块都会退出,因此显式给出的break,并不会退出switch语句块所在的循环。
如果想要在switch中break掉外层的循环,可以给循环语句块加上label后,然后break label,这个label就是该循环语句的名字,label的下一行必须为循环语句,也即下一行必须紧接的是for:
Loop:
for i := 0; i <= 9; i++ {
fmt.Println("In loop", i)
switch {
case i == 5:
fmt.Println("Hit switch")
break Loop
}
}
//output
In loop 0
In loop 1
In loop 2
In loop 3
In loop 4
In loop 5
Hit switch
这种通过label来跳出循环的,内部可跨多层跳出外层循环,具体是:
Loop:
for {
for i := 0; i <= 9; i++ {
fmt.Println("In loop", i)
switch {
case i == 1:
fmt.Println("Hit switch")
break Loop
}
}
}
//output
In loop 0
In loop 1
Hit switch
Label指向/代表的是其后紧跟的语句块或语句,一个label可以是一个if、for等语句块,也可以是一条语句,例如fmt.Println("helloworld")。
continue也可以后接一个label:
func main() {
Loop:
for i := 0; i < 10; i++ {
fmt.Println("before continue")
continue Loop
fmt.Println("after continue")
}
}//这样after continue就不会打印出来
一个case分支可以判断多个值进行匹配,用逗号进行分隔:
case val1,val2,val3:
switch var1 {
case val1:
...
case val2:
...
fallthrough
default:
...
}//var1 可以是任意类型的变量,表达式。val1、val2可以是值也可以是表达式,但必须为同类型的值
没有写fallthrough的时候分支就好像一个断点一样,执行到下一个断点就结束该switch语句
fallthrough后的case不会进行匹配( fallthrough 不会判断下一条 case 的表达式结果是否为 true ),直接执行语句:
switch a {
case 1, 23, 10:
fmt.Println("case1")
fallthrough
case 20:
fmt.Println("case2")
default:
fmt.Println("default case")
}// 输出 case1 case2
switch语句也可以搭配声明语句一起使用:
map1 := map[string]string{}
map1["hello"] = "world"
switch a,_:=map1["hello"];a{
case "world":
fmt.Println("hello->world")
case "hello":
fmt.Println("hello->hello")
default:
fmt.Println("no needed ")
}
//output
hello->world
甚至switch后不需要跟变量,只要case后跟了一个布尔运算表达式即可:
switch {
case true:
fmt.Println("hello->world")
case false:
fmt.Println("hello->hello")
default:
fmt.Println("no needed ")
}
//output
hello->world
Type Switch
switch语句可用于type-switch语句来判断某个interface变量中实际存储的变量类型
type-switch中不能使用fallthrough
switch x.(type){
case type:
statement(s);
case type:
statement(s);
/* 你可以定义任意个数的case */
default: /* 可选 */
statement(s);
}
var b interface{}
switch i := b.(type) {
case nil:
fmt.Println("case1", i)
case int:
fmt.Println("case2")
default:
fmt.Println("default case")
}//输出case1 <nil>
上述的i:=b.(type),如果在switch语句中匹配到了某个类型,则i是这个类型的值;而如果都没有匹配到,例如最终到了default分支,则i是b的类型:
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
//output
Twice 21 is 42
"hello" is 5 bytes long
I don't know about type bool!
其实上述这个type switch语句,还是根据i.(type)进行了分支判断,只不过v根据分支判断有不同的结果。
select语句
select语句可以看成是用于通信的switch语句,有点APUE中select函数的意思
select {
case communication clause :
statement(s);
case communication clause :
statement(s);
/* 你可以定义任意数量的 case */
default : /* 可选 */
statement(s);
}
特点:
1.每个case都是一个通信语句
2.所有的channel表达式都会被求值、所有被发送的表达式也会被求值
3.如有某个通信(case)可执行,则只执行这个,其他的忽略
4.若有多个case满足条件,则会随机的选择一个case进行执行,其他的不会执行
否则:
1.如果有default分支,则执行该分支
2.若无default分支,则select语句会阻塞(循环等待),直到有通信可以运行,Go不会重新对channel和值进行求值。
package main
import "fmt"
func main() {
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no communication\n")
}
}//输出 no communication
for循环
Go语言的循环语句只有一个for语句,能够实现c++的条件循环、while循环相同的功能
for init;condition;post{
}//类似于C++中的for (int i =0;i<100;i++)
for condition {
} //类似while (i<100)
for {
} // 类似 while(1)
//也有范围for的用法
for key,value:=range oldMap{
newMap[key]=value
}
for key:=range oldMap{
fmt.Println(key)
}
//通过这样range也可只取第一个返回值,不需要用下划线去忽略第二个返回值
package main
import "fmt"
func main() {
strings := []string{"google", "runoob"}
for i, s := range strings {
fmt.Println(i, s)
}
numbers := [6]int{1, 2, 3, 5}
for i,x:= range numbers {
fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
}
}