条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true
来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句。

语句 描述


if 语句 if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
if else 语句 if 语句 后可以使用可选的 else 语句,else 语句中的表达式在布尔表达式为 false 时执行。
if 嵌套语句 你可以在 ifelse if 语句中嵌入一个或多个 ifelse if 语句。
switch 语句 switch 语句用于基于不同条件执行不同动作。
select 语句 select 语句类似于 switch 语句,但是 select 会随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。

# if 语句

条件判断:

1
2
3
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
}

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"
func main() {
   /* 定义局部变量 */
   var a int = 10
 
   /* 使用 if 语句判断布尔表达式 */
   if a < 20 {
       /* 如果条件为 true 则执行以下语句 */
       fmt.Printf("a 小于 20\n" )
   }
   fmt.Printf("a 的值为 : %d\n", a)
}

#

# if else 语句

条件判断:

1
2
3
4
5
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
}

if 在表达式为 true 时执行里面的语句,在表达式为 false 时执行 false 里面的语句
实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
import "fmt"
func main() {
   /* 局部变量定义 */
   var a int = 100;
 
   /* 判断布尔表达式 */
   if a < 20 {
       /* 如果条件为 true 则执行以下语句 */
       fmt.Printf("a 小于 20\n" );
   } else {
       /* 如果条件为 false 则执行以下语句 */
       fmt.Printf("a 不小于 20\n" );
   }
   fmt.Printf("a 的值为 : %d\n", a);
}

#

# if 嵌套语句

条件判断:

1
2
3
4
5
6
if 布尔表达式 1 {
/* 在布尔表达式 1 为 true 时执行 */
if 布尔表达式 2 {
/* 在布尔表达式 2 为 true 时执行 */
}
}

嵌套的理解很简单,就是在第一个 if 语句的表达式为 true 时执行第二个 if 语句
实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import "fmt"
func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int = 200
 
   /* 判断条件 */
   if a == 100 {
       /* if 条件语句为 true 执行 */
       if b == 200 {
          /* if 条件语句为 true 执行 */
          fmt.Printf("a 的值为 100 , b 的值为 200\n" );
       }
   }
   fmt.Printf("a 值为 : %d\n", a );
   fmt.Printf("b 值为 : %d\n", b );
}

#

# switch 语句

着重记录一下 switch 语句和 select 语句

条件判断:

1
2
3
4
5
6
7
8
switch var1 {
case val1:
...
case val2:
...
default:
...
}

可以理解为寻找匹配的值,在 case 的几个选项中寻找匹配 var1 的值,如果匹配到则执行相应 case 底下的代码,如果都没有匹配到则执行 default 底下的代码

变量 var1 可以是任何类型,而 val1 和 val2
则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。
您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1,
val2, val3。

总结一下就是 var1 可以是任意类型,而 val1 和 val2 可以是任意值但是类型必须和 var1 相同,如有多个符合 case 条件的值可以放在同一行,如 case
10,20,30: a=1

switch 可以有两种表达方式,如下实例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import "fmt"
func main() {
   /* 定义局部变量 */
   var grade string = "B"
   var marks int = 90
   switch marks {
      case 90: grade = "A"
      case 80: grade = "B"
      case 50,60,70 : grade = "C"
      default: grade = "D"  
   }
   switch {
      case grade == "A" :
         fmt.Printf("优秀!\n" )    
      case grade == "B", grade == "C" :
         fmt.Printf("良好\n" )      
      case grade == "D" :
         fmt.Printf("及格\n" )      
      case grade == "F":
         fmt.Printf("不及格\n" )
      default:
         fmt.Printf("差\n" );
   }
   fmt.Printf("你的等级是 %s\n", grade );      
}

type switch

switch 语句还可以被用于 type-switch 来判断某个 interface
变量中实际存储的变量类型。

语法格式:

1
2
3
4
5
6
7
8
9
switch x.(type){
case type:
statement(s);
case type:
statement(s);
/* 你可以定义任意个数的case */
default: /* 可选 */
statement(s);
}

判断 x 的类型,当然这也可以声明一个变量来进行接收再用 case 去判断变量所接收的类型
实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "fmt"
func main() {
   var x interface{}
     
   switch i := x.(type) {
      case nil:  
         fmt.Printf(" x 的类型 :%T",i)                
      case int:  
         fmt.Printf("x 是 int 型")                      
      case float64:
         fmt.Printf("x 是 float64 型")          
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )      
      default:
         fmt.Printf("未知型")    
   }  
}

fallthrough

使用 fallthrough 会强制执行后面的 case 语句,fallthrough
不会判断下一条 case 的表达式结果是否为 true。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
func main() {
    switch {
    case false:
            fmt.Println("1、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("2、case 条件语句为 true")
            fallthrough
    case false:
            fmt.Println("3、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("4、case 条件语句为 true")
    case false:
            fmt.Println("5、case 条件语句为 false")
            fallthrough
    default:
            fmt.Println("6、默认 case")
    }
}

执行结果为:

1
2
3
2、case 条件语句为 true
3、case 条件语句为 false
4、case 条件语句为 true

简单说明一下该实例,第一个 case
true 为第二条,因此第一次进入的便是第二个 case 语句,在第二个 case 语句之后加上了 fallthrough,这时就不管第三个语句是否为 true 都进入执行,第三个后面也加了 fallthrough,不管第四个 case 是否为 true 也是直接进入执行语句,但是第四个 case 末没有 fallthrough,因此第五个 case 就得进行判断,发现是 false 那就不执行。case 中的代码有被执行过,因此 default 中的代码不会被执行。最终输出的为 2、3、4
#

# select 语句

select 是 Go 中的一个控制结构,类似于 switch 语句。
select 语句只能用于通道操作,每个 case
必须是一个通道操作,要么是发送要么是接收。
select
语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
如果多个通道都准备好,那么 select
语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default
块中的代码。

语法:

1
2
3
4
5
6
7
8
9
10
11
select {
  case <- channel1:
    // 执行的代码
  case value := <- channel2:
    // 执行的代码
  case channel3 <- value:
    // 执行的代码
    // 你可以定义任意数量的 case
  default:
    // 所有通道都没有准备好,执行的代码
}

以下描述了 select 语句的语法:
每个 case 都必须是一个通道
所有 channel 表达式都会被求值
所有被发送的表达式都会被求值
如果任意某个通道可以进行,它就执行,其他被忽略。
如果有多个 case 都可以运行,select
会随机公平地选出一个执行,其他不会执行。
否则:
如果有 default 子句,则执行该语句。
如果没有 default 子句,select 将阻塞,直到某个通道可以运行;Go
不会重新对 channel 或值进行求值。

应用实例 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
    "fmt"
    "time"
)
func main() {
    c1 := make(chan string)
    c2 := make(chan string)
    go func() {
        time.Sleep(1 * time.Second)
        c1 <- "one"
    }()
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "two"
    }()
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        }
    }
}

在这个实例中创建了两个通道 c1 和 c2,select 在等待两个通道的数据,如果 c1 收到了就执行 case
msg1,如果 c2 收到了就执行 case msg2
应用实例 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
import "fmt"
func main() {
  // 定义两个通道
  ch1 := make(chan string)
  ch2 := make(chan string)
  // 启动两个 goroutine,分别从两个通道中获取数据
  go func() {
    for {
      ch1 <- "from 1"
    }
  }()
  go func() {
    for {
      ch2 <- "from 2"
    }
  }()
  // 使用 select 语句非阻塞地从两个通道中获取数据
  for {
    select {
    case msg1 := <-ch1:
      fmt.Println(msg1)
    case msg2 := <-ch2:
      fmt.Println(msg2)
    default:
      // 如果两个通道都没有可用的数据,则执行这里的语句
      fmt.Println("no message received")
    }
  }
}

上述实例中我们定义了两个通道,并启动了两个协程(Goroutine)从这两个通道中获取数据。在
main 函数中,我们使用 select
语句在这两个通道中进行非阻塞的选择,如果两个通道都没有可用的数据,就执行
default 子句中的语句。
以下实例执行后会不断地从两个通道中获取到的数据,当两个通道都没有可用的数据时,会输出
"no message received"。

在第二个实例中,启动了协程从这两个通道中获取数据,更快捷高效,因为没有对 for 循环语句做限制,因此它会不断从通道中获取数据,直到没有数据获取了就执行 default 中的代码,输出 no
message received

更新于