Go 语言编程 — 逻辑控制语句

情到浓时终转凉″ 提交于 2020-08-13 00:57:14

目录

条件判断语句

在这里插入图片描述

if/else 语句

在这里插入图片描述
示例:

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

}

可见,Golang 中的条件表达式不需要使用 “()” 括起来。

switch 语句

switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。

在这里插入图片描述

与 C 语言不通,Golang 中的 switch 匹配项后面也不需要再加 break 语句。switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case。如果我们需要执行后面的 case,可以使用 fallthrough 语句。

格式:

switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

其中,变量 var1 可以是任何类型,而 val1 和 val2 则是同类型的任意值,类型不被局限于常量或整数,但必须是相同的类型。或者最终结果为相同类型的表达式。如果希望通过布尔数据类型来进行判定,则 switch 关键字后不需要紧跟条件表达式。

同时,还可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3

示例:

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

fallthrough 语句

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

示例:

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

结果:

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

type-switch 语句

Golang 中,还可以使用 type-switch 来判断某个 interface(接口)变量中实际存储的变量类型。

格式:

switch x.(type) {
    case type:
       statement(s);      
    case type:
       statement(s); 
    /* 你可以定义任意个数的case */
    default: /* 可选 */
       statement(s);
}

示例:

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("未知型")    
   }  
}

select 语句

select 语句类似于用于通信的 switch 语句。区别在于 select 语句是专为 channel(通道)而设计的,每个 case 必须是一个通信操作,要么是发送(ch <- )要么是接收(<- ch)。

select 随机执行一个可运行的 case。如果没有可运行的 case,它将阻塞,直到有 case 可运行。其中,default 子句应该总是可运行的。

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

格式:

elect {
    case communication clause:
       statement(s);      
    case communication clause:
       statement(s);
    /* 你可以定义任意数量的 case */
    default: /* 可选 */
       statement(s);
}

示例:

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

简而言之,select 会循环检测所有 case 的条件表达式,如果有满足则执行并退出,否则一直循环检测

package main

import (
    "fmt"
    "time"
)

func Chann(ch chan int, stopCh chan bool) {
    var i int
    i = 10
    for j := 0; j < 10; j++ {
        ch <- i
        time.Sleep(time.Second)
    }
    stopCh <- true
}

func main() {

    ch := make(chan int)
    c := 0
    stopCh := make(chan bool)

    go Chann(ch, stopCh)

    for {
        select {
            case c = <- ch:
                fmt.Println("Recvice c:", c)
                fmt.Println("channel")
            case s := <- ch:
                fmt.Println("Receive s:", s)
            case _ = <- stopCh:
                goto end
        }
    }
end:
}

结果:

Recvice c: 10
channel
Receive s: 10
Recvice c: 10
channel
Receive s: 10
Receive s: 10
Recvice c: 10
channel
Receive s: 10
Receive s: 10
Recvice c: 10
channel
Recvice c: 10
channel

循环语句

for 循环

在这里插入图片描述

Golang 仅支持 for 循环,但 Golang 的 for 循环具有 3 种形式。

  1. 和 C 语言的 for 一样,但循环控制语句不需要使用 “()” 括起来:
for init; condition; post { }
  • init:一般为赋值表达式,给控制变量赋初值;
  • condition:关系表达式或逻辑表达式,循环控制条件;
  • post:一般为赋值表达式,给控制变量增量或减量。

for 循环的执行过程如下:

  1. 先对 init 赋初值;
  2. 判别赋值表达式 init 是否满足 condition 条件,若其值为真,则执行循环体内语句,然后执行 post。进入第二次循环,再判别 condition;否则判断 condition 的值为假,不满足条件,就终止 for 循环,执行循环体外语句。

示例:计算 1 到 10 的数字之和

package main

import "fmt"

func main() {
        sum := 0
        for i := 0; i <= 10; i++ {
                sum += i
        }
        fmt.Println(sum)
}
  1. 和 C 的 while 循环一样,省略 init 和 post:
for condition { }

示例:

package main

import "fmt"

func main() {
    sum := 1
    
    for sum <= 10 {
         sum += sum
    }
    fmt.Println(sum)
}
  1. 和 C 的 for(;;) 一样,省略 init、condition 和 post:
for { }

示例,无限循环

package main

import "fmt"

func main() {
    sum := 0
    for {
        sum++        // 无限循环下去
    }
    fmt.Println(sum) // 无法输出
}

Range 迭代器

Golang 提供了 range(范围)关键字,类似于 Python 的迭代器。for 循环的 range 格式可以对 Slice(切片)、Map、数组、字符串等进行迭代循环。

格式:

for key, value := range oldMap {
    newMap[key] = value
}

示例:For-each range 循环,这种格式的循环可以对 Slice、Map、数组、字符串进行迭代输出各个元素。

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

结果:

0 google
1 runoob
第 0 位 x 的值 = 1
第 1 位 x 的值 = 2
第 2 位 x 的值 = 3
第 3 位 x 的值 = 5
第 4 位 x 的值 = 0
第 5 位 x 的值 = 0

循环控制语句

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!