Go学习: 流程控制

5 篇文章 0 订阅

4. 流程控制

4.1 条件判断(if)

在Go语言中,可以通过if关键字进行条件判断,格式如下:

if 表达式1 {

​ 分支1

} else if 表达式2 {

​ 分支2

} else {

​ 分支3

}

当表达式 1结果为 rue 时,执行分支1,否则判断表达式2 ,如果满足则执行分支2,都不满足时,则执行分支3 。表达式2 、分支2 和分支3 都是可选的,可以根据实际需要进行选择

要进行选择。

Go 规定与 if 匹配的左括号“ {”必须与 if 和表达式放在同一行,如果尝试将“{”放在其 位置,将会触发编译错误。

同理,与 else 匹配的“{”也必须与 else 在同一行, else 也必须与上一个 if 或else if的右边的大括号在一行。

特殊写法:

可以在if表达式之前添加一个执行语句,再根据变量的值进行判断,代码如下:

if err := Connect(); err != nil {
	fmt.Println(err)
	return
}

这种写法可以将返回值与判断放在一行进行处理,而且返回值的作用范围被限制在if、else 语句组合中。

4.2 构建循环(for)

Go语言中的所有循环类型均可以使用for关键字来完成。

基于语句和表达式的基本for循环格式如下:

for 初始语句;条件表达式; 结束语句 {

​ 循环体代码

}

循环体不停地进行循环,直到条件表达式返回false时自动退出循环,执行for循环体之后的语句。

for循环可以通过break、goto、return、panic语句强制退出循环。for的初始语句、条件表达式、结束语句的详细介绍如下。

4.2.1 for中的初始语句

初始语句是在第一次循环前执行的语句,一般使用初始语句执行变量初始化,如果变量在此处被声明,其作用域将被局限在这个for的范畴内

初始语句可以被忽略,但是初始语句之后的分号必须要写,代码如下:

step := 2
for ; step > 0; step-- {
	fmt.Println(step)
}

这段代码将step 放在 for 的前面进行初始化, for 中没有初始语句, 此时 step 的作用域就比在初始语句中声明 step 要大

4.2.2 for中的条件表达式

对每次循环开始前计算的表达式,如果表达式为true,则循环继续,否则循环结束。条件表达式可以被忽略,被忽略条件的表达式默认形成无限循环

  1. 结束循环时带可执行语句的无限循环

    下面代码忽略条件表达式,但是保留结束语句,代码如下:

    var i int
    for ; ; i++ {
    	if i > 10 {
    		break
    	}
    }
    
  2. 无限循环

    上面的代码还可以改写为更美观的写法,代码如下:

    var i int
    for {
    	if i > 10 {
    		break
    	}
    	i++
    }
    
  3. 只有一个循环条件的循环

    var i int
    for i <= 10 {
    	i++
    }
    

4.2.3 for中结束语句

在结束每次循环前执行的语句,如果循环被break、goto、return、panic等语句强制退出,结束语句不会被执行。

4.3 键值循环(for range)

Go语言可以使用for range遍历数组、切片、字符串、map及通道(channel)。通过for range遍历的返回值有一定的规律:

  • 数组、切片、字符串返回索引和值
  • map返回键和值
  • 通道(channel)只返回通道内的值。

4.3.1 遍历数组、切片

在遍历代码中,key和value分别代表切片的下标下标对应的值。下面的代码展示如何遍历切片,数组也是类似的遍历方法:

for key, value := range []int{1,2,3,4} {
	fmt.Printf("key:%d, value:%d", key, value)
}

4.3.2 遍历字符串

可以通过for range组合,对字符串进行遍历,遍历时,key和value分别代表字符串的索引(base0)和字符串中的每一个字符。

下面这段代码展示了如何遍历字符串:

var str = "hello 你好"
for key, value := range str {
	fmt.Printf("key:%d, value:0x%x", key, value)
}

代码中的v变量,实际类型时rune,实际上就是int32, 以十六进制打印出来的就是字符的编码。

4.3.3 遍历map

对于map类型来说,for range遍历时,key和value分别代表map的索引键key和索引对应的值,一般称为map的键值对,因为它们总是一对一对的出现。下面的代码演示了如何遍历map.

m := map[string]int {
	"hello":100,
	"world":200,
}
for key, value := range m {
	fmt.Printf("key:%d, value:%d", key, value)
}

4.3.4 遍历通道(channel)

for range可以遍历通道(channel),但是 通道在遍历时,只输出一个值,即管道内的类型对应的数据

通道遍历如下:

 c := make(chan int)
 
 go func() {
 	c <- 1
 	c <- 2
 	c <- 3
 	c <- 4
 	colse(c)
 }()
 
 for v := range c {
 	fmt.Println(v)
 }
 

4.4 分支选择(switch)

Go语言改进了switch的语法设计,避免人为造成失误。Go语言的switch中的每一个case间时独立的代码块,不需要同过break语句跳出当前代码以避免执行到下一行。示例代码如下:

var a = "hello"
switch a {
case "hello":
	fmt.Println(1)
case "world":
	fmt.Println(2)
default:
	fmt.Println(0)
}

上面例子中,每 case 均是字符串格式,且使用了default 分支, Go规定每个switch 只能有一个 default 分支

  1. 一分支多值

    当出现多个case要放在一起的时候,可以像下面的代码这样写:

    var a = "mum"
    switch a {
    case "mum", "daddy":
    	fmt.Println("family")
    }
    
  2. 分支表达式

​ case后不仅仅只是常量,还可以和if一样添加表达式,代码如下:

 var r int = 11
 switch {
 case r > 10 && r < 20 :
 	fmt.Println(r)
 }

注意: 这种情况的switch后面不再跟判断变量,连判断的目标都没有了。

4.4.2 跨越case的fallthrough

为了兼容一些移植代码,依然加入了fallthrough关键字来实现这一功能,代码如下:

var a = "hello"
switch {
case a == "hello":
	fmt.Println(1)
	fallthrough
case a != "world":
	fmt.Println(2)
}

4.5 跳转到指定的代码标签(goto)

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程。

4.5.1 退出多层循环

退出多层的循环,示例代码如下:

//外循环
for x :=0; x < 10; x++ {
	//内循环	
	for y := 0; y < 10; y++ {
		//满足条件退出所有循环
		if y == 2 {
			goto OUT
		}
	}
}
//手动返回,避免执行标签
	return
//标签
OUT:
	fmt.Println("out loop")

4.5.2 统一错误处理

多处错误处理存在代码重复时非常棘手,后期陆续在这些代码中如果添加更多的判断,就需要在每块雷同代码中依次修改,极易造成疏忽和错误。

如果使用 goto 语句来实现同样的逻辑:

     err := firstCheck()
     if err  != nil {
        goto OnExit	//发生错误时跳转错误标签OnExit
     }

     err = secondCheck()
      if err  != nil {
        goto OnExit
     }
     fmt.Println("done")
     return
 
 OnExit:		//汇总所有流程进行错误打印并退出进程
 	fmt.Println(err)
 	exitProcess()

4.6 跳出指定循环(break)

break语句可以结束for、switch和select的代码块。break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块标签要求必须定义在对应的for、switch和select的代码块上

OuterLoop:
	for i := 0; i < 2; i++ {
		for j := 0; j < 5; j++ {
			switch j {
			case 2:
				fmt.Println(i,j)
				break OuterLoop
			case 3:
				fmt.Println(i,j)
				break OuterLoop
			}
		}
	}

4.7 继续下一次循环(continue)

continue语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for循环内使用。在continue语句后添加标签时,表示开始标签对应的循环。例如:

OuterLoop:
	for i := 0; i < 2; i++ {
		for j := 0; j < 5; j++ {
			switch j {
			case 2:
				fmt.Println(i,j)
				continue OuterLoop
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值