Go 语言核心 36 讲
郝林
《Go 并发编程实战》作者,前轻松筹大数据负责人
79610 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 55 讲
Go 语言核心 36 讲
15
15
1.0x
00:00/00:00
登录|注册

18 | if语句、for语句和switch语句

位置靠上的case子句总会被选中
数组是值类型
切片是引用类型
在if语句中的作用域
在类型switch语句中对被判断类型的值做相应的类型转换
普通case子句的编写顺序很重要
重复的子表达式会导致编译错误
有限的类型转换
判等操作要求类型相同
切片与数组的区别
range表达式结果值会被复制
迭代变量只代表索引值
2. 初始化子句声明的变量的作用域
1. 类型转换
switch表达式和case表达式
携带range子句
思考题
switch语句
for语句
Go语言流程控制语句

该思维导图由 AI 生成,仅供参考

在上两篇文章中,我主要为你讲解了与go语句、goroutine 和 Go 语言调度器有关的知识和技法。
内容很多,你不用急于完全消化,可以在编程实践过程中逐步理解和感悟,争取夯实它们。
现在,让我们暂时走下神坛,回归民间。我今天要讲的if语句、for语句和switch语句都属于 Go 语言的基本流程控制语句。它们的语法看起来很朴素,但实际上也会有一些使用技巧和注意事项。我在本篇文章中会以一系列面试题为线索,为你讲述它们的用法。
那么,今天的问题是:使用携带range子句的for语句时需要注意哪些细节? 这是一个比较笼统的问题。我还是通过编程题来讲解吧。
本问题中的代码都被放在了命令源码文件 demo41.go 的main函数中的。为了专注问题本身,本篇文章中展示的编程题会省略掉一部分代码包声明语句、代码包导入语句和main函数本身的声明部分。
numbers1 := []int{1, 2, 3, 4, 5, 6}
for i := range numbers1 {
if i == 3 {
numbers1[i] |= i
}
}
fmt.Println(numbers1)
我先声明了一个元素类型为int的切片类型的变量numbers1,在该切片中有 6 个元素值,分别是从16的整数。我用一条携带range子句的for语句去迭代numbers1变量中的所有元素值。
在这条for语句中,只有一个迭代变量i。我在每次迭代时,都会先去判断i的值是否等于3,如果结果为true,那么就让numbers1的第i个元素值与i本身做按位或的操作,再把操作结果作为numbers1的新的第i个元素值。最后我会打印出numbers1的值。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了Go语言中的基本流程控制语句if语句、for语句和switch语句的使用技巧和注意事项。通过面试题的形式,讲解了使用携带range子句的for语句时需要注意的细节,并通过实例展示了对切片进行迭代并进行条件判断和操作的过程。文章还涉及了对switch语句中的switch表达式和case表达式之间的联系,以及对判等操作的讲解。总结来说,本文内容丰富,涵盖了Go语言中流程控制语句的多个方面,适合读者快速了解和掌握相关技术特点。文章通过实例讲解,使得读者能够在编程实践中逐步理解和应用这些基本流程控制语句,夯实相关知识。文章中还提到了一些细节和注意事项,如在迭代数组或切片时只有一个迭代变量的情况下无法迭代出其中的元素值,以及switch语句中的case表达式的子表达式结果值需要与switch表达式的结果值判等等。这些细节对于技术初学者来说是非常有价值的。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言核心 36 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(30)

  • 最新
  • 精选
  • 咖啡色的羊驼
    好久没留言了, 1.断言判断value.(type) 2.if的判断的域和后面跟着的花括号里头的域。和函数雷同,参数和花括号里头的域同一个

    作者回复: 好,继续加油吧。

    2018-09-21
    29
  • 大王叫我来巡山
    了解这些只能证明您对这个语言足够的了解,但是实际中谁会写这么蛋疼的代码呢,这一篇通篇其实说明的还是go语言中关于类型转换的内容

    作者回复: 这些语法细节你要是不注意的话,说不定什么时候就会“踩坑”。文章中的代码是为了演示原理而设计的,因此不一定适用于生产。 你可以去看看哪些热门开源项目的代码,里面仍然会有体现这些知识点的代码。所以不充分理解这些,可能看复杂些的项目源码都费劲。

    2019-09-09
    2
    16
  • Felix
    关于数组变切片那个地方。我理解如下:切片自己不拥有任何数据,它只是底层数组的一种表示,对切片的任何操作都会被反映到底层数组中去。 package main import "fmt" func main() { numbers3 := []int{1, 2, 3, 4, 5, 6} maxIndex3 := len(numbers2) - 1 //6-1= 5 for i, e := range numbers3 { // 0:1 1:2 2:3 3:4 4:5 5:6 if i == maxIndex3 { // 5 numbers3[0] += e // 0,7 } else { numbers3[i+1] += e // 1:3 } // 0:1 1:(1+2)3 2:3 3:4 4:5 5:6 // 0:1 1:3 2:(3+3)6 3:4 4:5 5:6 // 0:1 1:3 2:6 3:(6+4)10 4:5 5:6 // 0:1 1:3 2:6 3:10 4:(10+5)15 5:6 // 0:1 1:3 2:6 3:10 4:15 5:(15+6)21 // 0:(21+1)22 1:3 2:6 3:10 4:15 5:21 // 22 3 6 10 15 21 } fmt.Println(numbers3) }

    作者回复: 对,所以我们才称切片为引用类型。它本身只是底层数组及其存储状态的一种描述。

    2019-12-09
    9
  • Dr.Li
    感觉go的语法有点变态啊

    作者回复: 要包容:)工具而已。

    2018-09-21
    2
    8
  • 博博
    老师遇到一个问题,希望能帮忙解答下! 您在文章中说range表达式的结果值是会被复制的,那么是所有的都会被复制么? 我看了资料,发现字典和通道类型好像没有发生复制! // Lower a for range over a map. // The loop we generate: // var hiter map_iteration_struct // for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) { // index_temp = *hiter.key // value_temp = *hiter.val // index = index_temp // value = value_temp // original body // } 很是疑惑,希望能得到指点!谢谢

    作者回复: 你看的是 Go 的源码吗?我没找到这段代码。不过我看了下 mapiterinit 函数的代码。其中还是有复制的。只不过,对于这些引用类型的值来说,即使有复制也只会复制一些指针而已,底层数据结构是不会被赋值的。

    2019-07-23
    6
  • hiyanxu
    老师,我想问一下,range的副本,是说k、v是副本,还是被迭代的数组是副本? 我自己测试在for的里面和外面数组地址是一样的

    作者回复: 迭代变量是副本。另外在Go程序里的变量地址是不能完全说明问题的,因为goroutine的栈空间有可能会被优化。

    2018-12-23
    3
    5
  • while (1)等;
    文中说“被迭代的对象是range表达式结果值的副本而不是原值。”,那被迭代的对象是切片时,可以理解为指针的副本吗?也就是指针和指针的副本指向同一地址?

    作者回复: 不是指针的副本,是切片结构体的副本,切片结构体中有指向底层数组的指针。这个副本与原本会指向同一个底层数组。

    2021-05-09
    3
  • Rico
    在类型switch语句中,我们怎样对被判断类型的那个值做相应的类型转换? ------val.(type) 在if语句中,初始化子句声明的变量的作用域是什么? -------变量作用域为if语句{}内部的范围

    作者回复: 第二个回答不太严谨,应该是:if语句块内,因为 else 的 {} 也是包含其中的。

    2021-03-08
    2
    2
  • My dream
    Go1.11已经正式发布,最大的一个亮点是增加了对WebAssembly的实验性支持。老师要讲一下不?我们都不懂这个有什么意义

    作者回复: 主要是写Web端的时候有些用,不过我不觉得用处很大,因为现在大型网站都是前后端分离的。最后我视情况而定吧。

    2018-09-21
    2
  • jack
    index := 0 var mu sync.Mutex fp := func(i int, fn func()) { for { mu.Lock() if index == i { fn() index++ mu.Unlock() break } mu.Unlock() time.Sleep(time.Nanosecond) } } for i := 0; i < 10; i++ { go func(i int) { fn := func() { fmt.Println(i) } fp(i, fn) }(i) } // 这里就简单点了,不用 sync.WaitGroup 等那些结束了 time.Sleep(time.Second)

    作者回复: 功能上可以,性能上还有待进一步推敲。比如:不用锁。

    2022-07-20
收起评论
显示
设置
留言
30
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部