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)
        }  
}