命令记不住

登陆

Go 流程控制

流程控制

1.选择结构语句

  • if语句

在编程中实现选择判断结构就是用 if
if结构语法

if 条件判断 {
	// 代码语句
}

条件判断如果为真(true),那么就执行if大括号中的语句。
条件判断如果为假(false),那么就执行else大括号中的语句。
if代码块或else代码块,必须有一块被执行。

  • if判断布尔变量
age, ok := ages["bob"]
if !ok {
	"bob不是字典中的建,age == 0"
}

合并为一条语句

if age, ok := ages["bob"]; !ok {
	"bob不是字典中的建,age == 0"
}
  • if else if结构语法

从上到下依次判断条件,如果结果为真,就执行 { } 内的代码

if 条件判断1 {
	// 代码语句1
} else if 条件判断2 {
	// 代码语句2
} else if 条件判断3 {
	// 代码语句3
} else {
	// 代码语句4
}
//通过键盘获取数据  存放变量中
fmt.Scan(&score) //阻塞式请求
package main

import "fmt"

func main() {
	//if 表达式 {代码}  如果表达式为真 执行{}的代码
	//if 表达式 {代码1} else{代码2} 如果表达式为真 执行代码1内容 如果为假 执行代码2
	//if 表达式1 {代码1} else if表达式2{代码2}else{代码3} 依次判断表达式 满足条件执行

	score := 0
	//通过键盘获取数据  存放变量中
	fmt.Scan(&score) //阻塞式请求

	if score > 700 {
		fmt.Println("我要上清华")
	} else if score > 680 {
		fmt.Println("我要上北大")
	} else {
		fmt.Println("我要上蓝翔")
	}
}
  • switch
switch 变量或者表达式的值 {
case 值1:
// 代码语句1
case 值2:
// 代码语句2
case 值3:
// 代码语句3
default:
	// 代码语句4
}

执行流程:
程序执行到switch处,首先将变量或者表达式的值计算出来,然后拿着这个值依次跟每个case后面所带的值进行匹配,一旦匹配成功,则执行该case所带的代码,执行完成后,跳出switch-case结构。

如果,跟每个case所带的值都不匹配。就看当前这个switch-case结构中是否存在default,如果有default,则执行default中的语句,如果没有default,则该switch-case结构什么都不做。

注意:
某个case 后面跟着的代码执行完毕后,不会再执行后面的case,而是跳出整个switch结构, 相当于每个case后面都跟着break(终止)。
但是如果想执行完成某个case后,强制执行后面的case,可以使用fallthrough。

switch 表达式{case 值1: 代码1 case 值2: 代码2} 哪个分支满足条件指向哪条

package main

import "fmt"

func main() {
	//switch 表达式{case 值1: 代码1  case 值2: 代码2} 哪个分支满足条件指向哪条
	//输入月份  计算天数
	day := 0
	m := 0
	fmt.Scan(&m)
	switch m {
	//如果有多个值  执行相同的代码,可以使用逗号分隔
	case 1, 3, 5, 7, 8, 10, 12:
		day = 31
		//fallthrough  执行完当前分支  继续向下执行
	case 2:
		day = 28
	case 4, 6, 9, 11:
		day = 30
	default:
		day = -1
	}
	fmt.Println(day)
}
  • 浮点型因为精度问题可能在switch中认为是同一个值
func main() {
	pi := 3.14
	//浮点型因为精度问题可能在switch中认为是同一个值
	switch pi {
	case 3.140000000000000000019999999:
		fmt.Println(pi)
	case 3.14:
		fmt.Println(pi)
	}
}
  • switch后面不跟条件判断,直接在case内进行判断

像if语句那样去进行判断

package main

import (
	"fmt"
)

func main() {
	score := 0
	fmt.Scan(&score)

	switch {
	case score > 700:
		fmt.Println("我要上蓝翔")
	case score < 700:
		fmt.Println("我要去搬砖")
	}
}

2 循环结构语句

  • for语句

语法结构如下:

for 表达式1;表达式2;表达式3 {
//循环体
}

表达式1 :定义一个循环的变量,记录循环的次数
表达式2:一般为循环条件,循环多少次
表达式3:一般为改变循环条件的代码,使循环条件终有不再成立
循环体:重复要做的事情

package main

import "fmt"

func main() {
	sum := 0
	//循环体计算1-100的和
	for i := 1; i <= 100; i++ {
		sum += i
	}
	fmt.Println(sum)
}

for 表达式1;表达式2;表达式3{
代码
}
for 表达式{
代码
}
for range 集合{
代码
}

package main

import "fmt"

func main() {
	//水仙花数
	//一个三位数 各个位数的立方和等于本身的数
	for i := 100; i <= 999; i++ {
		a := i / 100     //百位
		b := i / 10 % 10 //十位
		c := i % 10      //个位
		if a*a*a+b*b*b+c*c*c == i {
			fmt.Println(i)
		}
	}
}
  • 嵌套循环

循环语句之间可以相互嵌套:

for 循环条件{
for 循环条件{
//执行代码
} }

package main

import "fmt"

func main() {
	//嵌套循环
	//外层执行一次 内层执行一周期
	for i := 0; i < 100; i++ {
		for j := 0; j < 50; j++ {
			fmt.Printf("外层=%d 内层=%d\n", i, j)
		}
	}
}
  • 冒泡排序
package main

import "fmt"

func main() {
	//冒泡排序   比较两个相邻数据元素  满足条件  交换数据位置
	slice := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	//外层控制行,表示要执行的次数
	for i := 0; i < len(slice); i++ {
		//内存控制列 表示比较次数
		for j := 0; j < len(slice); j++ {
			//比较两个相邻元素   大于号:升序排序   小于号:降序排序
			if slice[j] < slice[i] {
				//交换数据的值  =  实现多重赋值
				slice[j], slice[i] = slice[i], slice[j]
			}
		}
	}
	fmt.Println(slice)
}
  • 跳出语句
  • break语句

在循环语句中可以使用break跳出语句:
当它出现在循环语句中,作用是跳出当前内循环语句,执行后面的代码。
当它出现在嵌套循环语句中,跳出最近的内循环语句,执行后面的代码。

  • continue语句

在循环语句中,如果希望立即终止本次循环,并执行下一次循环,此时就需要使用continue语句。

break跳出

#内层 j==5
package main

import "fmt"

func main(){
	//break 跳出循环
	for i := 0 ; i < 10 ; i++{
		for j := 0 ; j< 10 ; j++{
			if j==5{
				break
			}
			fmt.Println(i,j)
		}
	}
}

执行到j==5时内层终止循环,但是外层继续执行循环,最终结果为[0-9][0-4]
#外层 i==5 
package main

import "fmt"

func main(){
	//break 跳出循环
	for i := 0 ; i < 10 ; i++{
		for j := 0 ; j< 10 ; j++{
			if i==5{
				break
			}
			fmt.Println(i,j)
		}
	}
}
执行到j==5时内层终止循环,但是外层继续执行循环,最终结果为[0-4][0-9]和[6-9][0-9]

continue 结束本次循环 继续下次循环

// 计算1-100偶数的和
package main

import "fmt"

func main() {
	//continue 结束本次循环 继续下次循环
	//计算1-100偶数的和
	sum := 0
	for i := 1; i <= 100; i++ {
		//奇数
		if i%2 == 1 {
			continue
		}
		sum += i
	}
	fmt.Println(sum)
}
  • goto 无条件跳转语句
package main

import "fmt"


func main() {
	//goto 无条件跳转语句
	fmt.Println("性感法师")
FLAG:
	fmt.Println("在线讲课")
	fmt.Println("轻松就业")
	goto FLAG
	fmt.Println("日薪越亿")
}

//死循环
在线讲课
轻松就业
在线讲课
轻松就业
在线讲课
轻松就业
在线讲课
轻松就业
在线讲课
轻松就业
exit status 2
  • goto 不可以跳入循环内部 不可以跳出函数
package main

import "fmt"

func main() {
	//goto 不可以跳入循环内部  不可以跳出函数
HERE:
	for i := 0; i <= 10; i++ {
		if i == 5 {
			//break
			goto HERE
		}
		fmt.Println(i)
	}
	fmt.Println("程序执行结束...")
}

3.优化案例

package main

import "fmt"

func main0901() {
	//古代数学家 张丘建 算经  公鸡5钱/只 母鸡3钱/只 小鸡 1钱/3只  需要用百钱买百鸡
	//公鸡 20只
	//母鸡 33只
	//小鸡 100只
	count := 0
	for i := 0; i <= 20; i++ {
		for j := 0; j <= 33; j++ {
			for k := 0; k <= 100; k += 3 {
				count++
				if i+j+k == 100 && i*5+j*3+k/3 == 100 {
					fmt.Println("公鸡:", i, "母鸡:", j, "小鸡:", k)
				}
			}
		}
	}
	fmt.Println("次数:", count)
}

func main0902() {
	//古代数学家 张丘建 算经  公鸡5钱/只 母鸡3钱/只 小鸡 1钱/3只  需要用百钱买百鸡
	//公鸡 20只
	//母鸡 33只
	//小鸡 100只
	count := 0
	for i := 0; i <= 20; i++ {
		for j := 0; j <= 33; j++ {
			count++
			//小鸡个数=100-公鸡-母鸡
			k := 100 - i - j //百鸡
			if i*5+j*3+k/3 == 100 && k%3 == 0 {
				fmt.Println("公鸡:", i, "母鸡:", j, "小鸡:", k)
			}
		}
	}
	fmt.Println("次数:", count)
}

//短路算法   if 条件判断  ||

func test() {
	//敲7 1-100数字 如果末尾带7  或者十位带7 或者7的倍数 需要敲桌子 正常数字打印
	for i := 1; i <= 100; i++ {
		if i%7 == 0 || i%10 == 7 || i/10 == 7 {
			fmt.Println("敲桌子")
		} else {
			fmt.Println(i)
		}
	}
}
func main() {
	test()
}

4.select永久阻塞

启动协程处理任务,不希望main函数退出,可以使用永久阻塞

func main(){
    sever := webhooktesting.NewTestServer(nill)
    server.StartTLS()
    fmt.Println("serving on",server.URL)
    select {}
}

以上代码不包含case语句和default语句,那么协程将陷入永久阻塞

5.select快速检错

使用管道来传输错误,此时可以使用select语句快速检查管道中是否有错误,避免陷入循环

errCh :=make(chan error,active)
jm.deleteJobPods(&job,activePods,errCh)
select{
case manmageJobErr = <-errCh:
    if manageJobErr !=nil{
        break
}
default:   //没有错误快速结束检查
}

上面的select仅用于尝试从管道中读取错误信息,如果没有错误信息,那么不会陷入阻塞

6.select限时等待

使用管道来管理函数的上下文,此时可以使用select来创建只有一定时效的管道

func waitForStopOrTimeoput(stopCh <- chan struct{},timeout time.Duration) <- chan struct{}{
    stopChWithTimeout := make(chan  struct{})
    go func() {
        select{
        case <- stopCh://自然结束
        case <- time.After(timeout)://最长等待时间长
        }
        close(stopChWithTimeout)
    }()
    return stopChWithTimeout
}

该函数返回一个和管道,可用于在函数之间传递,但该管道会在指定时间后自动关闭

.

推荐阅读