06、Golang 教程 - 流程控制语句

一、分支结构

1. if 分支

Go语言提供了以下几种条件判断语句:

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

1.1 单分支

 if 条件表达式 {

  逻辑代码
}

当条件表达式为 true 时,就会执行得的代码。

条件表达式左右的 () 可以不写,也建议不写。
if 和表达式中间,一定要有空格。
在Golang 中,{} 是必须有的,就算你只写一行代码。

 package main

import "fmt"

func main() {

    var count int = 100
    if count > 30 {

        fmt.Println("数量充足!")
    }
}

// ------ //
数量充足!

1.2 双分支

 if 条件表达式 {

   逻辑代码1
} else {

   逻辑代码2
}

// 下面代码格式是错误的
if 条件表达式 {

   逻辑代码1
}
else {

   逻辑代码2
} 

示例:

 package main

import "fmt"

func main() {

    var count int = 70
    if count < 30 {

        fmt.Println("库存不足")
    } else {

        fmt.Println("库存充足")
    }
}

1.3 多分支

 if 条件表达式1 {

    逻辑代码1
} else if 条件表达式2 {

    逻辑代码2
}
......
else {

    逻辑代码n
}

示例:

 // 方法一
package main

import "fmt"

func main() {

    var grade int
    fmt.Println("请输入分数:") // 提示语句
    fmt.Scanf("%d",&grade)
    a := grade

    if a >= 90 {

        fmt.Println("成绩为 A")
    }
    if a >= 80 && a < 90 {

        fmt.Println("成绩为 B")
    }
    if a >= 60 && a < 80 {

        fmt.Println("成绩为 C")
    }
    if a < 60 {

        fmt.Println("成绩为 D")
    }
}

// 方法二
package main

import "fmt"

func main() {

    var grade int
    fmt.Println("请输入分数:") // 提示语句
    fmt.Scanf("%d",&grade)
    a := grade

    if a >= 90 {

        fmt.Println("成绩为 A")
    } else if a >= 80 {

     //else隐藏:score < 90
        fmt.Println("成绩为 B")
    } else if a >= 70 {

     //score < 80
        fmt.Println("成绩为 C")
    } else if a >= 60 {

     //score < 70
        fmt.Println("成绩为 D")
    } else {

     //score < 60
        fmt.Println("成绩为 E")
    }
}

1.4 嵌套

 if 布尔表达式 1 {

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

      /* 在布尔表达式 2 为 true 时执行 */
   }
}

示例:

 package main

import "fmt"

func main() {

    var a int = 100
    var b int = 200

    if a == 100 {

        if b == 200 {

            fmt.Printf("a 的值为 %d\n",a)
            fmt.Printf("b 的值为 %d\n",b)
        }
    }
}

// -----双重判断用户密码输入----- //
package main

import "fmt"

func main() {

    var a int
    var b int
    fmt.Printf("请输入密码:\n")
    fmt.Scan(&a)
    if a == 654321 {

        fmt.Printf("请再次输入密码:")
        fmt.Scan(&b)
        if b == 123456 {

            fmt.Printf("密码正确,门锁已打开!")
        } else {

            fmt.Printf("密码错误,已报警!")
        }
    } else {

        fmt.Printf("密码错误,已报警!")
    }
}

2. switch 分支

  • switch 后是一个表达式(即:常量值、变量、一个有返回值的函数等都可以)
  • case 后面的值如果是常量值(字面量),则要求不能重复
  • case 后的各个值的数据类型,必须和 switch 的表达式数据类型一致
  • case 后面可以带多个值,使用逗号间隔。比如 case val1,val2,...
  • case 后面不需要带 break
  • default 语句不是必须的,位置也是随意的
  • switch 后也可以不带表达式,当做 if 分支来使用
  • switch 后也可以直接声明/定义一个变量,分号结束,不推荐
  • switch 穿透,利用 fallthrough 关键字,如果在 case 语句块后增加 fallthrough,则会继续执行下一个 case,也叫 switch 穿透
 switch 表达式 {

    case 值1,值2,...:
        语句块1
    case 值3,值4,...:
        语句块2
    ......
    default:
        语句块
}

示例:

 package main

import "fmt"

func main() {

    var score float64
    fmt.Println("请输入分数(0-100):")
    fmt.Scanf("%f",&score)
    switch score/10 {

    case 10 :
        fmt.Println("等级为 A")
    case 9 :
        fmt.Println("等级为 A")
    case 8 :
        fmt.Println("等级为 B")
    case 7 :
        fmt.Println("等级为 B")
    case 6 :
        fmt.Println("等级为 C")
    default:
        fmt.Println("不合格")
    }
}

Type Switch

  • switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。
  • Type Switch 语法格式如下:
 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("未知型")    
   }  
}   // x 的类型 :<nil>

// ---------------------------- //
package main

import "fmt"

// 全局变量可以不被调用,函数中声明的变量一定要被调用
// type-Switch 语句判断数据类型
func main() {

    var num = 3.14
    make_type(num)
}

func make_type(x interface{

     }) {

    // 判断数据类型 type 只能使用搭配 Switch,如果想单独使用输出数据类型,需要使用反射
    switch i := x.(type) {

    case nil:
        fmt.Printf("数据类型为 %T",i)
    case int:
        fmt.Println("数据类型为 int")
    case float32,float64:
        fmt.Println("数据类型为浮点型")
    case string:
        fmt.Println("数据类型为字符串")
    case bool:
        fmt.Println("数据类型为 bool")
    default:
        fmt.Println("其他类型")
    }
 }  // 数据类型为浮点型

// -----反射判断数据类型-----//
package main

import (
    "fmt"
    "reflect"
)

// 全局变量可以不被调用,函数中声明的变量一定要被调用
// type-Switch 语句判断数据类型
func main() {

    var num *int
    fmt.Println("num 的数据类型:",reflect.TypeOf(num))
}   // num 的数据类型: *int

fallthrough

  • 使用 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

switch 从第一个判断表达式为 true 的 case 开始执行,如果 case 带有 fallthrough,程序会继续执行下一条 case,且它不会去判断下一个 case 的表达式是否为 true。

多条件匹配

 switch{

    case 1,2,3,4:
    default:
}
  • 不同的 case 之间不使用 break 分隔,默认只会执行一个 case。
  • 如果想要执行多个 case,需要使用 fallthrough 关键字,也可用 break 终止。
 switch{

    case 1:
    ...
    if(...){

        break
    }

    fallthrough // 此时switch(1)会执行case1和case2,但是如果满足if条件,则只执行case1

    case 2:
    ...
    case 3:
}

3. select 语句

  • select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。
  • select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。

语法:

 select {

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

每个 case 都必须是一个通信。
所有 channel 表达式都会被求值。
所有被发送的表达式都会被求值。
如果任意某个通信可以进行,它就执行,其他被忽略。
如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。
否则:
如果有 default 子句,则执行该语句。
如果没有 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
/// ------------------------------------ ///
package main

import (
    "fmt"
    "time"
)

func Chann(ch chan int, stopCh chan bool) {

    for j := 0; j < 10; j++ {

        ch <- j
        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("Receive C", c)
        case s := <-ch:
            fmt.Println("Receive S", s)
        case _ = <-stopCh:
            goto end
        }
    }
end:
}

https://blog.csdn.net/ma2595162349/article/details/112911710

二、循环结构

Go语言提供了以下几种类型循环处理语句:

循环类型 描述
for 循环 重复执行语句块
循环嵌套 在 for 循环中嵌套一个或多个 for 循环

1. for 循环

Go语言的 For 循环有 3 种形式,只有其中的一种使用分号。

  • 和 C 语言的 for 一样:
 for init; condition; post {

      }
  • 和 C 的 while 一样:
 for condition {

      }
  • 和 C 的 for(;;) 一样:
 for {

      }

示例:

 // 计算 1 到 10 的数字之和:55
package main

import "fmt"

func main() {

        sum := 0
        for i := 0; i <= 10; i++ {

                sum += i
        }
        fmt.Println(sum)
}

// 无限循环
package main

import "fmt"

func main() {

    for true  {

        fmt.Printf("这是无限循环。\n");
    }
}

// For-each 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)
        }  
}

2. 循环控制语句

  • 循环控制语句可以控制循环体内语句的执行过程。
  • GO 语言支持以下几种循环控制语句:
控制语句 描述
break 语句 经常用于中断当前 for 循环或跳出 switch 语句
continue 语句 跳过当前循环的剩余语句,然后继续进行下一轮循环。
goto 语句 将控制转移到被标记的语句。
return 语句 返回函数值
 package main
import "fmt"
func main(){

        //功能:求1-100的和,当和第一次超过300的时候,停止程序
        var sum int = 0
        for i := 1 ; i <= 100 ; i++ {

                sum += i
                fmt.Println(sum)
                if sum >= 300 {

                        //停止正在执行的这个循环:
                        break 
                }
        }
        fmt.Println("-----ok")
}

/// --- 标签的使用 --- ///
package main

import "fmt"

func main() {

label:
    for i:=1;i<=5;i++ {

        fmt.Println("外层:",i)
        for j:=1;j<=8;j++ {

            fmt.Println("内层",j)
            if j > 5 {

                break label
            }
        }
    }
}

continue

 package main
import "fmt"
func main(){

        //功能:输出1-100中被6整除的数:
        //方式1:
        // for i := 1; i <= 100; i++ {

        //  if i % 6 == 0 {

        //      fmt.Println(i)
        //  }
        // }
        //方式2:
        for i := 1; i <= 100; i++ {

                if i % 6 != 0 {

                        continue //结束本次循环,继续下一次循环
                }
                fmt.Println(i)
        }
}

// -----------------------//
package main
import "fmt"
func main(){

        //双重循环:
        for i := 1; i <= 5; i++ {

                for j := 2; j <= 4; j++ {

                        if i == 2 && j == 2 {

                                continue
                        }
                        fmt.Printf("i: %v, j: %v \n",i,j)
                }
        }
        fmt.Println("-----ok")
}
// -----------------------//
package main
import "fmt"
func main(){

        //双重循环:
        label:
        for i := 1; i <= 5; i++ {

                for j := 2; j <= 4; j++ {

                        if i == 2 && j == 2 {

                                continue label
                        }
                        fmt.Printf("i: %v, j: %v \n",i,j)
                }
        }
        fmt.Println("-----ok")
}

// -----------------------//
package main

import "fmt"

/*continue使用标记*/
func main() {

    fmt.Println("外层循环开始")
abc:
    for i := 1; i <= 5; i++ {

        fmt.Println("外层:", i)
        for j := 10; j < 20; j++ {

            fmt.Println("内层:", j)
            if j > 15 {

                continue abc
            }
        }
    }
    fmt.Println("外层循环结束")
}

goto

 package main
import "fmt"
func main(){

        fmt.Println("hello golang1")
        fmt.Println("hello golang2")
        if 1 == 1 {

                goto label1 //goto一般配合条件结构一起使用
        }
        fmt.Println("hello golang3")
        fmt.Println("hello golang4")
        fmt.Println("hello golang5")
        fmt.Println("hello golang6")
        label1:
        fmt.Println("hello golang7")
        fmt.Println("hello golang8")
        fmt.Println("hello golang9")
}

// ------ //
package main

import "fmt"

/*标签在goto语句之前  实现类似循环操作*/
/*标签在goto语句之后  实现跳过语句步骤执行*/
func main() {

    //初始值
    i := 4

    fmt.Println(i)
    i++
    //退出条件
    if i == 5 {

        goto HERE
    }

    fmt.Println("语句1")
    fmt.Println("语句2")
    fmt.Println("语句3")
HERE: //跳转标记
    fmt.Println("语句4")
}

return

 package main
import "fmt"
func main(){

        for i := 1; i <= 100; i++ {

                fmt.Println(i)
                if i == 14 {

                        return //结束当前的函数
                }
        }
        fmt.Println("hello golang")
}