• 技术文章 >后端开发 >Golang

    一文浅析Golang中的流程控制

    青灯夜游青灯夜游2022-11-25 21:07:20转载238
    本篇文章带大家学习一下Golang,聊聊Go语言基础中的流程控制,希望对大家有所帮助。

    php入门到就业线上直播课:进入学习

    Go语言基础之流程控制主要包括以下内容:

    【相关推荐:Go视频教程

    1. 条件语句if

    Go语言中if条件判断的格式如下:

    if 表达式1 {
        分支1
    } else if 表达式2 {
        分支2
    } else{
        分支3
    }

    前端的同学想必对js相对熟悉,相对于js来说,go表达式去掉了括号(),但同时给了一些约束,与if匹配的左括号{必须与if和表达式放在同一行,{放在其他位置会触发编译错误。 同理,与else匹配的{也必须与else写在同一行,else也必须与上一个ifelse if右边的大括号在同一行。

    x := 0
    
    // if x > 10        // Error: missing condition in if statement
    // {
    // }
    
    if n := "abc"; x > 0 {     // 初始化语句未必就是定义变量, 如 println("init") 也是可以的。
        println(n[2])
    } else if x < 0 {    // 注意 else if 和 else 左大括号位置。
        println(n[1])
    } else {
        println(n[0])
    }
    
    
    
     *不支持三元操作符(三目运算符) "a > b ? a : b"。
     
    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)
    }
    
    
    以上代码执行结果为:
    a 小于 20
    a 的值为 : 10

    2. 条件语句switch

    switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 Golang switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。

    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 )
    }
    
    
    
    以上代码执行结果为:
    优秀!
    你的等级是 A

    3. 条件语句select

    select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

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

    以下描述了 select 语句的语法:

        每个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

    select可以监听channel的数据流动

    select的用法与switch语法非常类似,由select开始的一个新的选择块,每个选择条件由case语句来描述

    与switch语句可以选择任何使用相等比较的条件相比,select有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作

     select { //不停的在这里检测
        case <-chanl : //检测有没有数据可以读
        //如果chanl成功读取到数据,则进行该case处理语句
        case chan2 <- 1 : //检测有没有可以写
        //如果成功向chan2写入数据,则进行该case处理语句
    
    
        //假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源
        default:
        //如果以上都没有符合条件,那么则进行default处理流程
        }

    在一个select语句中,Go会按顺序从头到尾评估每一个发送和接收的语句。

    如果其中的任意一个语句可以继续执行(即没有被阻塞),那么就从那些可以执行的语句中任意选择一条来使用。 如果没有任意一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况: ①如果给出了default语句,那么就会执行default的流程,同时程序的执行会从select语句后的语句中恢复。 ②如果没有default语句,那么select语句将被阻塞,直到至少有一个case可以进行下去。

    典型用法-超时判断

    //比如在下面的场景中,使用全局resChan来接受response,如果时间超过3S,resChan中还没有数据返回,则第二条case将执行
    var resChan = make(chan int)
    // do request
    func test() {
       select {
       case data := <-resChan:
           doData(data)
       case <-time.After(time.Second * 3):
           fmt.Println("request time out")
       }
    }
    
    func doData(data int) {
       //...
    }

    4. 循环语句for

    和if一样,相对于js,go语言的for循环也去掉了括号(),其他并没有太大的区别。

    package main
    
    import "fmt"
    
    func main() {
    
       var b int = 15
       var a int
    
       numbers := [6]int{1, 2, 3, 5}
    
       /* for 循环 */
       for a := 0; a < 10; a++ {
          fmt.Printf("a 的值为: %d\n", a)
       }
    
       for a < b {
          a++
          fmt.Printf("a 的值为: %d\n", a)
          }
    
       for i,x:= range numbers {
          fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
       }   
    }
    
    
    以上实例运行输出结果为:
    
        a 的值为: 0
        a 的值为: 1
        a 的值为: 2
        a 的值为: 3
        a 的值为: 4
        a 的值为: 5
        a 的值为: 6
        a 的值为: 7
        a 的值为: 8
        a 的值为: 9
        a 的值为: 1
        a 的值为: 2
        a 的值为: 3
        a 的值为: 4
        a 的值为: 5
        a 的值为: 6
        a 的值为: 7
        a 的值为: 8
        a 的值为: 9
        a 的值为: 10
        a 的值为: 11
        a 的值为: 12
        a 的值为: 13
        a 的值为: 14
        a 的值为: 15
        第 0 位 x 的值 = 1
        第 1 位 x 的值 = 2
        第 2 位 x 的值 = 3
        第 3 位 x 的值 = 5
        第 4 位 x 的值 = 0
        第 5 位 x 的值 = 0

    5. 循环语句range

    Golang range类似迭代器操作,返回 (索引, 值) 或 (键, 值)。

    for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

    for key, value := range oldMap {
        newMap[key] = value
    }
    package main
    
    func main() {
        s := "abc"
        // 忽略 2nd value,支持 string/array/slice/map。
        for i := range s {
            println(s[i])
        }
        // 忽略 index。
        for _, c := range s {
            println(c)
        }
        // 忽略全部返回值,仅迭代。
        for range s {
    
        }
    
        m := map[string]int{"a": 1, "b": 2}
        // 返回 (key, value)。
        for k, v := range m {
            println(k, v)
        }
    }
    
    输出结果:
    
        97
        98
        99
        97
        98
        99
        a 1
        b 2

    for 和 for range有什么区别?

    主要是使用场景不同

    for可以遍历array和slice,遍历key为整型递增的map,遍历string

    for range可以完成所有for可以做的事情,却能做到for不能做的,包括遍历key为string类型的map并同时获取key和value,遍历channel

    6. 循环控制Goto、Break、Continue

    循环控制语句

    循环控制语句可以控制循环体内语句的执行过程。

    GO 语言支持以下几种循环控制语句:

    Goto、Break、Continue

        1.三个语句都可以配合标签(label)使用
        2.标签名区分大小写,定以后若不使用会造成编译错误
        3.continue、break配合标签(label)可用于多层循环跳出
        4.goto是调整执行位置,与continue、break配合标签(label)的结果并不相同

    break(跳出循环): continue(继续下次循环)break语句可以结束forswitchselect的代码块。break语句还可以在语句后面添加标签,表示退出某个标签对应的代码块,标签要求必须定义在对应的forswitchselect的代码块上。

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

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

    func gotoDemo1() {
    	var breakFlag bool
    	for i := 0; i < 10; i++ {
    		for j := 0; j < 10; j++ {
    			if j == 2 {
    				// 设置退出标签
    				breakFlag = true
    				break
    			}
    			fmt.Printf("%v-%v\n", i, j)
    		}
    		// 外层for循环判断
    		if breakFlag {
    			break
    		}
    	}
    }

    使用goto语句能简化代码:

    func gotoDemo2() {
    	for i := 0; i < 10; i++ {
    		for j := 0; j < 10; j++ {
    			if j == 2 {
    				// 设置退出标签
    				goto breakTag
    			}
    			fmt.Printf("%v-%v\n", i, j)
    		}
    	}
    	return
    	// 标签
    breakTag:
    	fmt.Println("结束for循环")
    }

    结束:

    再次提醒,需要进技术交流群的同学,可以加我微信fangdongdong_25,需要进前端工程师交流群的备注“前端”,需要进go后端交流群的备注“go后端”

    更多编程相关知识,请访问:编程视频!!

    以上就是一文浅析Golang中的流程控制的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:流程控制 后端 Go
    上一篇:go语言需要分号吗 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• golang怎么进行数据类型转换• go就是golang吗• golang有指针么• 详解Win系统下怎么搭建Golang开发环境• go语言有反射吗• linux支持go语言吗
    1/1

    PHP中文网