条件语句

if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行if后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。

  1. if condition {
  2. // do something
  3. }

如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。if else 后的两个代码块是相互独立的分支,只可能执行其中一个。

  1. if condition {
  2. // do something
  3. } else {
  4. // do something
  5. }

如果存在第三个分支,则可以使用下面这种三个独立分支的形式:

  1. if condition1 {
  2. // do something
  3. } else if condition2 {
  4. // do something else
  5. } else {
  6. // catch-all or default
  7. }

else-if 分支的数量是没有限制的,但是为了代码的可读性,还是不要在 if 后面加入太多的 else-if 结构。如果你必须使用这种形式,则把尽可能先满足的条件放在前面。

关键字 if else 之后的左大括号 { 必须和关键字在同一行,如果你使用了 else-if 结构,则前段代码块的右大括号 } 必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。

【示例】

  1. 判断一个字符串是够为空:

    • if str == "" {...}
    • if len(str) == 0 {...}
  2. 判断运行 Go 程序的操作系统类型,这可以通过常量 runtime.GOOS 来判断

    1. if runtime.GOOS == "windows" {
    2. ...
    3. } else { // Unix-like
    4. ...
    5. }

    这段代码一般被放在 init() 函数中执行。这儿还有一段示例来演示如何根据操作系统来决定输入结束的提示:

    1. var prompt = "Enter a digit, e.g. 3 "+ "or %s to quit."
    2. func init() {
    3. if runtime.GOOS == "windows" {
    4. prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")
    5. } else { //Unix-like
    6. prompt = fmt.Sprintf(prompt, "Ctrl+D")
    7. }
    8. }
  3. 函数 Abs() 用于返回一个整型数字的绝对值:

    1. func Abs(x int) int {
    2. if x < 0 {
    3. return -x
    4. }
    5. return x
    6. }
  4. isGreater 用于比较两个整型数字的大小:

    1. func isGreater(x, y int) bool {
    2. if x > y {
    3. return true
    4. }
    5. return false
    6. }

在条件语句中,还可以包含初始化语句:

  1. if initialization; condition {
  2. // do something
  3. }

例如:

  1. if val := 10; val > max {
  2. // do something
  3. }

但要注意的是,使用简短方式 := 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。最简单的解决方案就是不要在初始化语句中声明变量。

另外,else-if语句中也可以初始化变量,只是其作用域只在当前的else-if语句到结尾的else语句之间,在此之前的ifelse语句是无法访问的。

switch 语句

相比较 C 和 Java 等其它语言而言,Go 语言中的 switch 结构使用上更加灵活。它接受任意形式的表达式:

  1. switch var1 {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }

变量 var1 可以是任何类型,而 val1 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。前花括号 { 必须和 switch 关键字在同一行

可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3

每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。一旦成功地匹配到某个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您不需要特别使用 break 语句来表示结束。因此,程序也不会自动地去执行下一个分支的代码。如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 fallthrough 关键字来达到目的。

  1. switch i {
  2. case 0: fallthrough
  3. case 1:
  4. f() // 当 i == 0 时函数也会被调用
  5. }

fallthrough关键字之后,在当前概念 case 分支不能再出现语句了

case ...: 语句之后,不需要使用花括号将多行语句括起来,但可以在分支中进行任意形式的编码。当代码块只有一行时,可以直接放置在 case 语句之后。

同样可以使用 return 语句来提前结束代码块的执行。当在 switch 语句块中使用 return 语句,并且您的函数是有返回值的,还需要在 switch 之后添加相应的 return 语句以确保函数始终会返回。

可选的 default 分支可以出现在任何顺序,但最好将它放在最后。它的作用类似与 if-else 语句中的 else,表示不符合任何已给出条件时,执行相关语句。

switch 语句的第二种形式是不提供任何被判断的值(实际上默认为判断是否为 true),然后在每个 case 分支中进行测试不同的条件。当任一分支的测试结果为 true 时,该分支的代码会被执行。这看起来非常像链式的 if-else 语句,但是在测试条件非常多的情况下,提供了可读性更好的书写方式。

  1. switch {
  2. case i < 0:
  3. f1()
  4. case i == 0:
  5. f2()
  6. case i > 0:
  7. f3()
  8. }

前面的 switch 语句可以看做是值得判断,这里的 switch 是布尔条件的判断

switch 语句的第三种形式是包含一个初始化语句

  1. switch initialization; expression {
  2. case val1:
  3. ...
  4. case val2:
  5. ...
  6. default:
  7. ...
  8. }

switch 语句还可以被用于 type-switch来判断某个 interface 变量中实际存储的变量类型,后面再说。

for 语句

基于计数器的迭代

如果想要重复执行某些语句,Go 语言中只有 for 结构可以使用。不要小看它,这个 for 结构比其它语言中的更为灵活。

最简单的基于计数器的迭代,基本形式为:

  1. for 初始化语句; 条件语句; 修饰语句 {
  2. ...
  3. }

这三部分组成的循环的头部,它们之间使用分号;相隔,但并不需要括号 () 将它们括起来。

还可以在循环中同时使用多个计数器:

  1. for i, j := 0, N; i < j; i, j = i+1, j-1 {
  2. ...
  3. }

同样的,左花括号 { 必须和 for 语句在同一行,计数器的生命周期在遇到右花括号 } 时便终止。一般习惯使用 ijzix 等较短的名称命名计数器。

特别注意,永远不要在循环体内修改计数器,这在任何语言中都是非常差的实践!

可以将两个 for 循环嵌套起来:

  1. for i:=0; i<5; i++ {
  2. for j:=0; j<10; j++ {
  3. println(j)
  4. }
  5. }

基于条件判断的迭代

for 结构的第二种形式是没有头部的条件判断迭代(类似其它语言中的 while 循环),基本形式为:

  1. for 条件语句 {
  2. ...
  3. }

也可以认为这是没有初始化语句和修饰语句的 for 结构,因此 ;; 便是多余的了。

  1. package main
  2. import "fmt"
  3. func main() {
  4. var i int = 5
  5. for i >= 0 {
  6. i = i - 1
  7. fmt.Printf("The variable i is now: %d\n", i)
  8. }
  9. }
  10. /*
  11. * 输出:
  12. * The variable i is now: 4
  13. * The variable i is now: 3
  14. * The variable i is now: 2
  15. * The variable i is now: 1
  16. * The variable i is now: 0
  17. * The variable i is now: -1
  18. */

无限循环

条件语句是可以被省略的,如 i:=0; ; i++for { }for ;; { };; 会在使用 gofmt 时被移除):这些循环的本质就是无限循环。最后一个形式也可以被改写为 for true { },但一般情况下都会直接写 for { }

如果 for 循环的头部没有条件语句,那么就会认为条件永远为 true,因此循环体内必须有相关的条件判断以确保会在某个时刻退出循环。

无限循环的经典应用是服务器,用于不断等待和接受新的请求。

  1. for t, err = p.Token(); err == nil; t, err = p.Token() {
  2. ...
  3. }

for-range 结构

for-range 结构是 Go 语言特有的一种迭代结构,它在许多情况下都非常有用。它可以迭代任何一个集合,包括数组(array)和字典(map),同时可以获得每次迭代所对应的索引和值。一般形式为:

  1. for ix, val := range coll { }

要注意的是,val 始终为集合中对应索引的值的副本,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值(注:如果 val 为指针,则会产生指针的副本,依旧可以修改集合中的原值)。一个字符串是 Unicode 编码的字符(或称之为 rune)集合,因此您也可以用它迭代字符串:

  1. for pos, char := range str {
  2. ...
  3. }

每个 rune 字符和索引在 for-range 循环中是一一对应的。它能够自动根据 UTF-8 规则识别 Unicode 编码的字符。

还有其他一些用法,等说道相应的内容再举例

break和continue

  • break

    一般而言,直接结束最近的一层循环。但在 switchselect 语句中,break 语句的作用结果是跳过整个代码块,执行后续的代码。
  • continue

    结束本次迭代,直接开始下一次迭代,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件。 关键字 continue 只能被用于 for 循环中。

标签与goto

forswitchselect 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:)结尾的单词(gofmt 会将后续代码自动移至下一行)

  1. package main
  2. import "fmt"
  3. func main() {
  4. LABEL1:
  5. for i := 0; i <= 5; i++ {
  6. for j := 0; j <= 5; j++ {
  7. if j == 4 {
  8. continue LABEL1
  9. }
  10. fmt.Printf("i is: %d, and j is: %d\n", i, j)
  11. }
  12. }
  13. }

本例中,continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置。

【注意】continue 可以用 breakgoto 关键字替代,但是作用可能不同。

continue break 是指将自身功能作用到标签同一级别的循环体(例如多层循环,你想break直接结束整体的循环,就需要标签),goto 是直接到那一行执行,容易造成死循环。

『GoLang』控制结构的更多相关文章

  1. 『Golang』Martini框架入门

    本文介绍golang中的优秀web开发框架martini! 序 Martini框架是使用Go语言作为开发语言的一个强力的快速构建模块化web应用与服务的开发框架.Martini是一个专门用来处理Web ...

  2. 『Golang』MongoDB在Golang中的使用(mgo包)

    有关在Golang中使用mho进行MongoDB操作的最简单的例子.

  3. 『Golang』在Golang中使用json

    由于要开发一个小型的web应用,而web应用大部分都会使用json作为数据传输的格式,所以有了这篇文章. 包引用 import ( "encoding/json" "gi ...

  4. 『Golang』—— 标准库之 os

    Golang 的 os 库基本承袭 Unix 下 C 语言的用法 path 库: func Base(path string) string //取文件名,不含目录部分 func Dir(path s ...

  5. 『GoLang』fmt包的使用

    目录 1. fmt 包初识 2. 格式化 verb 应用 2.1 通用 2.2 布尔值 2.3 整数 2.4 浮点数与复数 2.5 字符串和 []byte 2.6 指针 2.7 其他 flag 2.8 ...

  6. 『GoLang』string及其相关操作

    目录 1. 字符串简介 2. 字符串的拼接 3. 有关 string 的常用处理 3.1 strings 包 3.1.1 判断两个 utf-8 编码字符串是否相同 3.1.2 判断字符串 str 是否 ...

  7. 『Golang』跨平台TUI(基于文字的用户界面)库Terbox-Go文档翻译

    原文 package termbox import "github.com/nsf/termbox-go" termbox-go 是一个用于创建跨平台TUI(基于文本的用户界面)的 ...

  8. 『Golang』Go简介以及环境搭建

    简介 go语言是由Google进行维护的一个编程语言,发布自2009年.其以良好的编程风格.优秀的并发机制被广大的技术人员所接受. 使用go语言开发的优秀的产品: Docker gocode lime ...

  9. 『Golang』—— 标准库之 time

    ... package main import ( "fmt" "time" ) func main() { time.AfterFunc(time.Milli ...

随机推荐

  1. spring框架学习日志一

    一.简介 1.对spring框架的简单理解 可以理解为它是一个管理对象的创建.依赖.销毁的容器 Spring 是一个开源框架. Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单 ...

  2. 一、vue基础语法(轻松入门vue)

    轻松入门vue系列 Vue基础语法 一.HelloWord 二.MVVM设计思想 三.指令 1. v-cloak 2. v-text 3. v-html 4. v-show 4. v-pre 5. v ...

  3. ProjectEuler 008题

    题目: The four adjacent digits in the 1000-digit number that have the greatest product are 9 9 8 9 = 5 ...

  4. TCP模拟QQ聊天功能

    需求: 模拟qq聊天功能:实现客户端与服务器(一对一)的聊天功能,客户端首先发起聊天,输入的内容在服务器端和客户端显示,然后服务器端也可以输入信息,同样信息在客户端和服务端显示. 提示: 客户端 1) ...

  5. redis>lua脚本

    String lua="local num=redis.call('incr',KEYS[1])\n"+"if tonumber(num)==1 then\n" ...

  6. 常用cron表达式

    0 0 10,14,16 * * ? 每天上午10点,下午2点,4点 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时 0 0 12 ? * WED 表示每个星期三中午12点 " ...

  7. redhat9 linux 网卡无法激活排障

    先查看自己的系统版本! [root@localhost root]# uname -a Linux localhost 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 ...

  8. yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:

    使用yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: 问题出现原因:yum包管理是使用python2 ...

  9. 第一次实战:XX漫画的XSS盲打

    第一次实战:XX漫画的XSS盲打 XSS盲打 盲打是一种惯称的说法,就是不知道有没有XSS漏洞存在的情况下,不顾一切的输入XSS代码在留言啊投诉窗口啊之类的地方,尽可能多的尝试XSS的语句,就叫盲打. ...

  10. You have mail in /var/mail/xxx

    因为配置 DDNS, 我添加了个 crontab 定时任务,每隔 1 分钟执行一段 python 脚本 然后就发现 terminal 经常提示 'You have mail in /var/mail/ ...