Go学习笔记 -- 流程控制 for、switch、select

news/2024/12/29 19:37:07/

文章目录

    • For
      • for [( init; condition; increment )]{}
      • for [condition]{}
      • for [Range]{}
      • 注意 Range 循环的对象是引用类型还是值类型!!!
    • Switch
      • 通过 switch 的值和 case 的值是否一致,判断逻辑分支
      • 省略条件表达式
      • Type Switch 判断接口类型
    • Select

For

Go 中的 For 循环可以分为三种形式:

for [( init; condition; increment )]{}

示例

for i := 0; i < 10; i++ {fmt.Println(i)
}

for [condition]{}

直接判断条件是否成立,相当于 while(condition)

i := 0
for i < 10 {fmt.Println(i)i++
}

当然我们可以省略关系表达式,那样就变成了一个无限循环 while(true)

for {fmt.Println("circle")
}

for [Range]{}

for range 是比较常用的循环手段,我们可以通过 range 来获取集合对象中元素的下标和值
其中 i 为元素下标,v 为元素值

list := []string{"one", "two", "three"}
for i, v := range list {fmt.Println(i, v)
}
-----------------------------
0 one
1 two
2 three

如果我们在 range 的左侧只有一个接收值,那么这个值表示元素下标

list := []string{"one", "two", "three"}
for i := range list {fmt.Println(i)
}
-----------------------------
0
1
2

注意 Range 循环的对象是引用类型还是值类型!!!

如下代码:
一个是 数组 list 一个是 切片 list_slice ,拥有同样的元素。
我们从第二个元素开始,将当前元素加上前一个元素的值作为新的值。
最后查看打印结果,两者却不一样,切片打印结果(一直累加)符合我们的预期。

list := [...]int{1, 1, 1, 1, 1}
for i, v := range list {if i+1 < len(list) {list[i+1] += v}
}
fmt.Println(list)list_slice := []int{1, 1, 1, 1, 1}
for i, v := range list_slice {if i+1 < len(list_slice) {list_slice[i+1] += v}
}
fmt.Println(list_slice)
-----------------------------------
[1 2 2 2 2]
[1 2 3 4 5]


原因如下:
首先,切片是引用类型的,数组是值类型的。
其次,循环伊始的 Range 表达式,只会在 for 语句执行时被求值一次,即,当运行 for i, v := range list 这一句之后,v 的值就已经被确认了。而且在数组循环中,v 的值其实只是一个副本,对原来值的修改不会影响到 v 的值。而对于引用类型的切片来说,其在循环时使用的副本实际上是指针的副本,副本指针指向的内存地址和原指针指向的内存地址是一样的,我们对 v 的修改就是对这个内存地址的值做的修改。

当然我们可以不在 Range 阶段求值,那样就会避免求值产生副本的问题。

list := [...]int{1, 1, 1, 1, 1}
for i := range list {if i+1 < len(list) {list[i+1] += list[i]}
}
fmt.Println(list)
-----------------------------------
[1 2 3 4 5]

Switch

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

通过 switch 的值和 case 的值是否一致,判断逻辑分支

  case 表达式中,可以放多个情况值。
  Go 语言中每个分支的最后默认都是有一个 break 的,使用 fallthrough 可以在走到当前分支后强制执行下一个 case

var ilist = []uint8{0, 1, 2, 3}
switch ilist[0] {
case 0:fmt.Println("000")
case 1:fmt.Println("111222")fallthrough
default:fmt.Println("default")
}
fmt.Println("--------分割线--------")
//使用 fallthrough 可以在走到当前分支后强制执行下一个 case 
switch ilist[2] {
case 0:fmt.Println("000")
case 1 , 2:fmt.Println("111222")fallthrough
default:fmt.Println("default")
}
----------------------------------
000
--------分割线--------
111222
default

省略条件表达式

也可以省略条件表达式,当作 if… else… 使用

var i int = 1
switch {
case i > 0 && i < 2:fmt.Println("1")
case i > 1 && i < 3:fmt.Println("2")
default:fmt.Println("default")
}
----------------------------------
1

Type Switch 判断接口类型

type Test struct {name string
}func main() {var test1 = Test{"测试"}switch i := interface{}(test1).(type) {case nil:fmt.Printf(" x 为空")case int:fmt.Printf("x 是 int 型")case bool, string:fmt.Printf("x 是 bool 或 string 型")default:fmt.Printf("其他类型 %T", i)}
}
--------------------------------
其他类型 main.Test

Select

  • select 是类似于 switch 的存在,但是他的分支需要绑定到通信操作上,select 中的 case 都是通信操作,要么接受,要么发送。
  • 在一开始所有 channel 表达式都会被求值,如果其中任意一个通信可以进行,那么他就会执行,其他的会被忽略。
  • 如果有多个case都可以运行,select 会随机公平地选出一个执行。其他不会执行。
  • 如果没有分支可执行,但有 default 子句,则执行 default 语句。
  • 如果没有分支可执行,且没有 default 字句,select 将阻塞,直到某个通信可以运行。

  如下代码,如果我们不屏蔽 default 分支,正常情况下最终将会打印十次 none value 结果,因为我们在执行 select 的时候,我们创建的三个通道里面都还没有值,过100 ms 之后我们才会放值,select 将走 default 分支。
  如果我们屏蔽掉 defalut 分支,打印结果如下,每一次的执行结果都可能不一样,哪一个通道中能先获取到值,就会执行对应分支的逻辑。

func goFunc(i int, ch *chan int) {time.Sleep(time.Millisecond * 100)*ch <- i
}func main() {ch0 := make(chan int, 3)ch1 := make(chan int, 3)ch2 := make(chan int, 3)for i := 0; i < 10; i++ {ch0 = make(chan int, 3)ch1 = make(chan int, 3)ch2 = make(chan int, 3)go goFunc(0, &ch0)go goFunc(1, &ch1)go goFunc(2, &ch2)select {case v := <-ch0:fmt.Printf("ch0 current value is %d\n", v)case v := <-ch1:fmt.Printf("ch1 current value is %d\n", v)case v := <-ch2:fmt.Printf("ch2 current value is %d\n", v)// default:// 	fmt.Printf("none value\n")}}//等待一段时间time.Sleep(time.Millisecond * 5000)
}
----------------------
ch1 current value is 1
ch1 current value is 1
ch0 current value is 0
ch1 current value is 1
ch2 current value is 2
ch0 current value is 0
ch2 current value is 2
ch0 current value is 0
ch1 current value is 1
ch2 current value is 2

同理,我们也可以通过校验通道是否可以写入值来控制分支。修改一下上面的代码,将其中一个分支修改为向通道中写值
执行到 select 时,所有通道中都没有值,但是 ch0 可以写入,所以会走第一个分支,打印结果全是 ch0 set value 9

func goFunc(i int, ch *chan int) {...}func main() {
...select {case ch0 <- 9:fmt.Printf("ch0 set value %d\n", <-ch0)
...}}
...
}
----------------------
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9
ch0 set value 9

http://www.ppmy.cn/news/2011.html

相关文章

项目经理如何做好跨部门沟通?

在项目管理中&#xff0c;计划不明确&#xff0c;职责定义不清晰&#xff0c;会造成沟通不畅&#xff0c;互相推诿的情况&#xff0c; 也会遇到跨部门沟通&#xff0c;就是相互相对独立的部门之间的沟通协调。这也让项目经理苦不堪言。 1、明确目标&#xff0c;计划制定 制…

kubelet源码分析-启动

前言 上一章节中我们了解到kubelet每个组件的作用与创建原理&#xff0c;那么在本章节中我们就一起看一下它是如何对每个组件进行启动的&#xff0c;组件与组件之间是如何进行相互作用的。 kubelet.Run() // Run starts the kubelet reacting to config updates func (kl *K…

【Linux|树莓派】分文件编程以及静态库动态库

一、分文件编程 简单来说树莓派的分文件编程就是将一个项目的代码放在不同的文件里面&#xff0c;然后在主函数添加一个头文件&#xff0c;这样会使#控制字体颜色主程序变得简单。 在编译的时候要将主函数和功能函数一起编译&#xff1a; 注意&#xff1a;include <stdio.h…

【华为上机真题 2022】流水线

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

鸢尾花数据种类预测、分析与处理、scikit-learn数据集使用、seaborn作图及数据集的划分

一、鸢尾花种类预测 Iris数据集是常用的分类实验数据集&#xff0c;由Fisher, 1936收集整理&#xff0c;Iris也称鸢尾花卉数据集&#xff0c;是一类多重变量分析的数据集 鸢尾花数据集包含了 4个属性&#xff08;特征值&#xff09; Sepal.Length&#xff08;花萼长度&#…

基于STM32的智能GPS定位系统(云平台、小程序)

背景及目标 前阵子&#xff0c;准确的说是好几个月前买了一辆电瓶车&#xff0c;当时呢因为车停得很随意&#xff0c;所以想给小电驴装一个GPS&#xff0c;一方面是防盗&#xff0c;另一方面是为了测速和绘制骑行轨迹&#xff0c;要是能联动电瓶车状态远程监测就更好了。当然我…

用二元泊松模型预测2022世界杯8强

用二元泊松模型预测2022世界杯8强 网上有很多文章用双泊松&#xff08;Double Poisson&#xff09;模型来预测世界杯比赛结果。但是双泊松模型有一个严重的缺陷&#xff0c;那就是它假设比赛中两队的比分是条件独立的。而我们都知道&#xff0c;在对抗性比赛中&#xff0c;两…

Hash与ZSet的常用命令以及其底层数据结构

目录hash类型命令hsethgethmsethmgethgetallhsetnxhdelhexitshincrby与hincrbyfloathkeys与hvalshlenhstrlen有序set型命令zaddzrange 与zrevrangezrangebyscore与zrevrangebyscorezcardzcountzscorezincrbyzrank 与 zrevrankzremzremrangebyrankzremrangebyscorezrangebylexzl…