Go在流程控制方面的特点如下:
  没有do和while循环,只有一个更广义的for语句。
  switch语句灵活多变,还可以用于类型判断。
  if语句和switch语句都可以包含一条初始化子语句。
  break语句和continue语句可以后跟一条标签(label)语句,以标识需要终止或继承的代码块。
  defer语句可以使我们更加方便地执行异常捕获和资源回收任务。
  select语句也用于多分支选择,但只与通道配合使用。
  go语句用于异步启动goroutine并执行指定函数。

1.代码块和作用域

代码块就是一个由花括号包裹地表达式和语句的序列。当然,代码块中也可以不包含任何内容,即:空代码块。
除了显式地代码块之外,还有一些隐式地代码块,说明如下:

  所有Go代码形成了一个最大地代码块,即:全域代码块
  每一个代码包中的代码共同组成了一个代码块,即:代码包代码块
  每一个源码文件都是一个代码块,即:源码文件代码块
  每一个if、for、switch和select语句都是一个代码块;
  每一个在switch或select语句中的case分支都是一个代码块。

在Go中,使用代码块表示词法上的作用域范围,具体规则如下:
  一个预定义标识符的作用域是全域代码块;
  表示一个常量、变量、类型或函数(不包括方法),且声明在函数之外的标识符的作用域是当前的代码包代码块;
  被导入的代码包的名称的作用域是当前的源码文件代码块;
  表示方法接收者、方法参数、类型或函数的标识符,如果被声明在函数内部,那么作用域就是包含其声明的那个最内层的代码块。

此外,我们还可以重新声明已经在外层代码块中声明过的标识符。
当在内层代码块中使用这个标识符时,它表示的总是那个在该代码块中与它绑定在一起的那个程序实体。
可以说,此时在外层代码块中声明的那个同名标识符并屏蔽了。例如

package main
import (
"fmt"
)
var v = "1,2,3" //最外层标识符
func main() {
v := []int{1, 2, 3} //第二次赋值
if v != nil {
var v = 123 //第三次赋值
fmt.Printf("%v\n", v)
}
}
//结果:123

其中,变量v被声明3次。当判断v是否非nil时,v代表的时那个切片。
而当v被打印时,它代表的确实那个整数。

2.if语句

if语句会根据条件表达式来执行两个分支中的一个。
如果那个表达式的结果是true,那么if分支会被执行,否则else分支会被执行。

例如:

var number int
//省略
if 100 < number {
number++
}

又如:

if 100 < number {
number++
}else {
number--
}

if语句还可以包含一条初始化的子语句,用于初始化局部变量:

if diff := 100 - number;100 < diff {
number++
}else {
number--
}

此外,它还支持串联:

if diff := 100 - number;100 < diff {  //先进行赋值操作,在逻辑判断
number++
}else if 200 < diff {
number--
}else {
number -= 2
}

其中条件表达式的求值顺序是自上而下的。只有第一个结果为true的表达式对应的分支会被选中并执行。
并且,只要上面的表达式的结果为true,其后的表达式就不会被求值。

3.switch语句

switch语句也提供了一种多行分支执行的方法。
它会用一个表达式或类型说明符与每一个case进行比较,并决定执行哪一个分支。

(1)表达式switch语句

在表达式switch语句中,switch表达式和所有case携带的表达式(也称为case表达式)都会被求值,并且执行顺序是自左向右、自下而上。
只有第一个与switch表达式的求值结果相等case表达式分支会被执行。
如果没有找到匹配的case表达式并且存在default case,那么default case的分支会执行。
注意,default case最多只有一个。
另外,switch表达式可以省略,这时true会作为switch表达式的结果。
示例:

package main
import (
"fmt"
)
var content string
//省略
switch content {
default:
fmt.Println("不知道什么语言")
case "python":
fmt.Fprintln("一门解释型语言")
case "go":
fmt.Println("一门编译型语言")

switch语句也可以包含一条子语句来初始化局部变量:

switch lang := strings.TrimSpace(content); lang {
default:
fmt.Println("不知道什么语言")
case "python":
fmt.Fprintln("一门解释型语言")
case "go":
fmt.Println("一门编译型语言")
}

可以在switch语句中使用fallthrough,来向下一个case语句转移流程控制权。

switch lang := strings.TrimSpace(content); lang {
case "Ruby":
fallthrough
case "Python":
fmt.Println("一门解释型语言")
case "C","Java","Go":
fmt.Println("一门编译型语言")
default:
fmt.Println("什么都不是")
}

只要lang的值等于Ruby或python,第2个case语句就会执行。其实可以放在一个case中。
每个case语句中的case表达式还可以有多个。
另外,break语句可以用来退出当前的switch语句。它由一个break关键字和一个可选的标签组成。

(2)类型switch语句

类型switch语句将对类型进行判定,而不是值。

var v interface{}
//省略
switch v.(type) {
case string:
fmt.Printf("The string '%s'.\n",v.(string))
case int,uint,int8,uint8:
fmt.Printf("The integer is %d.\n",v)
default:
fmt.Printf("Unsupported value.(type%T)\n",v)
}

类型switch语句的switch表达式会包含一个特殊的类型断言,例如v.(type)。
它虽然特殊,但是也要遵循类型断言的规则。其次,每个case表达式中包含的都是类型字面量而不是表达式。
最后fallthrough语句不允许出现在类型switch语句中。

类型断言switch语句的switch表达式还有一种变形写法。

switch i := v.(type) {
case string:
fmt.Printf("The string '%s'.\n",i)
case int,uint,int8,uint8:
fmt.Printf("The integer is %d.\n",i)
default:
fmt.Printf("Unsupported value.(type%T)\n",i)
}

这里的i := v.(type)使经类型转换后的值得以保存。i的类型一定会是v的值的实际类型。

4.for语句

for语句用于根据给定的条件重复执行一个代码块。这个条件或由for子句直接给出,或从range子句中获得。
(1)for子句

一条for语句中可以携带一条for子句。for子句可以包含初始化子句、条件子句和后置子句。

var number int
for i := 0; i < 100; i++ { //i := 0初始化语句 i++后置语句
number++
} var j uint = 1
for;j%5 != 0; j *= 3 { //省略初始化子句
number++
} for k := 1; k%5 != 0; { //省略后置子句
k *= 3
number++
}

在for子句的初始化子句和后置子句同时被省略,或者其中的所有部分都省略的情况下,分隔符":"可以省略。

var m = 1
for m < 50 {
m *= 3
}

(2)range子句

一条for语句可以携带一条range语句,这样就可以迭代出一个数组或者切片值中的每个元素、
一个字符串中的每个字符、或者一个字典值中的每个键-元素对,以及持续地接收一个通道类型值中的元素。
随着迭代的进行,每一次获取的迭代值(索引、元素、字符或键-元素对)都会赋给相应的迭代变量。

ints := []int{1, 2, 3, 4, 5}
for i, d := range ints {
fmt.Printf("Index:%d,value:%d\n", i, d)
}

在range关键字右边的是range表达式。range表达式一般只会在迭代开始前被求值一次.
针对range表达式的不同结果,range子句的行为也会不同。

使用range子句,有3点需要注意:
  a.若对数组、切片或字符串值进行迭代,且:=左边只有一个迭代变量时,一定要小心。
   这时只会得到其中元素的索引,而不是元素本身。
  b.迭代没有任何元素的数组值、为nil的切片值、为nil的字典值或为""的字符串值,
    并不会执行for语句中的代码。for语句在一开始就会直接结束执行,因为这些值的长度都为0.
  c.迭代为nil的通道值会让当前流程永远阻塞在for语句上。

go——流程控制的更多相关文章

  1. 第10章 Shell编程(4)_流程控制

    5. 流程控制 5.1 if语句 (1)格式: 格式1 格式2 多分支if if [ 条件判断式 ];then #程序 else #程序 fi if [ 条件判断式 ] then #程序 else # ...

  2. Shell命令和流程控制

    Shell命令和流程控制 在shell脚本中可以使用三类命令: 1)Unix 命令: 虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令.这些命令通常是用来进行文件和文字 ...

  3. PHP基础知识之流程控制的替代语法

    PHP 提供了一些流程控制的替代语法,包括 if,while,for,foreach 和 switch. 替代语法的基本形式是把左花括号({)换成冒号(:),把右花括号(})分别换成 endif;,e ...

  4. Python黑帽编程2.4 流程控制

    Python黑帽编程2.4  流程控制 本节要介绍的是Python编程中和流程控制有关的关键字和相关内容. 2.4.1 if …..else 先上一段代码: #!/usr/bin/python # - ...

  5. 使用yield进行异步流程控制

    现状 目前我们对异步回调的解决方案有这么几种:回调,deferred/promise和事件触发.回调的方式自不必说,需要硬编码调用,而且有可能会出现复杂的嵌套关系,造成"回调黑洞" ...

  6. [Java入门笔记] Java语言基础(四):流程控制

    流程控制指的是在程序运行的过程中控制程序运行走向的方式.主要分为以下几种: 顺序结构 顺序结构,顾名思义,是指程序从上往下逐步顺序执行.中间没有任何的判断和跳转. 分支结构 Java提供两种分支结构: ...

  7. node基础13:异步流程控制

    1.流程控制 因为在node中大部分的api都是异步的,比如说读取文件,如果采用回调函数的形式,很容易造成地狱回调,代码非常不容易进行维护. 因此,为了解决这个问题,有大神写了async这个中间件.极 ...

  8. Shell入门教程:流程控制(1)命令的结束状态

    在Bash Shell中,流程控制命令有2大类:“条件”.“循环”.属于“条件”的有:if.case:属于“循环”的有:for.while.until:命令 select 既属于“条件”,也属于“循环 ...

  9. Oracle中PL/SQL的执行部分和各种流程控制

    Oracle中PL/SQL的执行部分和异常部分 一.PL/SQL的执行部分. 赋值语句. 赋值语句分两种,一种是定义一个变量,然后接收用户的IO赋值:另一种是通过SQL查询结果赋值. 用户赋值举例: ...

  10. swift_简单值 | 元祖 | 流程控制 | 字符串 | 集合

    //: Playground - noun: a place where people can play import Cocoa var str = "Hello, playground& ...

随机推荐

  1. 第一百五十二节,封装库--JavaScript,表单验证--年月日注入

    封装库--JavaScript,表单验证--年月日注入 效果图 html <div id="reg"> <h2 class="tuo"> ...

  2. iOS开发中“此证书的签发者无效”的解决方式

    iOS开发过程中有时候会出现证书所有变成无效,例如以下图 然后进行打包的时候会提演示样例如以下警告:  解决方法:  第一步: 下载https://developer.apple.com/certif ...

  3. PHP第三方登录

    参考视屏:http://www.imooc.com/learn/596 php第三方登录-QQ登录OAuth协议基本原理QQ登录前置条件以及开放平台账号申请1,一个QQ号2,一个公网通过域名可访问的w ...

  4. java垃圾回收算法和垃圾收集器

    垃圾收集算法.垃圾回收算法.java垃圾收集器 目录1. 垃圾收集算法1)引用计数法2)根搜索法2. 垃圾回收算法1)复制算法2)标记-清除算法3)标记-整理算法4)分代收集算法3. java垃圾收集 ...

  5. (转)ThreadLocal

    转自:http://blog.csdn.net/lufeng20/article/details/24314381 Thread同步机制的比较 ThreadLocal和线程同步机制相比有什么优势呢?T ...

  6. 修改了JS代码,刷新网页后,加载的JS还是原来旧的?

    本地修改JS脚本后,刷新网页看一下修改后的执行效果,结果调试显示加载的JS还是原来旧的,反复刷新均无效,郁闷! 解决办法:清理一下浏览器缓存(长经验了!)     Ctrl+Shift+Del 清除G ...

  7. SourceTree --转载 SourceTree大文件上传提示POST git-receive-pack (chunked)相关问题记录

    前两天,更新了百度地图的SDK,更新完了通过SourceTree上传到Github 结果提示 :POST git-receive-pack (chunked), 在网上查询之后了解到这个提示的原因是因 ...

  8. 《Sqlserver》通过端口 8080 连接到主机 localhost 的 TCP/IP 连接失败。错误:“驱动程序收到意外的登录前响应。请验证连接属性,并检查 SQL Server 的实例正在主机上运行,且在此端口接受

    1. 点击 开始 --> 所有程序 --> Microsoft SQL Server2005 --> 配置工具-->SQL Server configuration Manag ...

  9. 转载别人的DLL DEll研究

    昨日,编了个DLL和EXE来进行了下测试,exe通过lib静态联编dll,来调用它的导出类,当改变DLL中导出类的结构(eg.成员变量的顺序等),从新发布DLL而不从新联结编译EXE,就会造成错误的执 ...

  10. PAT 甲级 1019 General Palindromic Number(简单题)

    1019. General Palindromic Number (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN ...