路漫漫其修远兮
吾将上下而求索

第5章总结:控制结构

第5章

5.1 
即使当代码块之间只有一条语句时,大括号也不可被省略,下面的格式和c一样
if condition {
	// do something	
}

if condition {
	// do something	
} else {
	// do something	
}

if condition1 {
	// do something	
} else if condition2 {
	// do something else	
}else {
	// catch-all or default
}

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

在有些情况下,条件语句两侧的括号是可以被省略的

下面是一些有用的例子
判断一个字符串是否为空:
if str == "" { ... }
if len(str) == 0 {...}

判断运行 Go 程序的操作系统类型,这可以通过常量 runtime.GOOS 来判断(第 2.2 节)。
 if runtime.GOOS == "windows"	 {
 	.	..
 } else { // Unix-like
 	.	..
 }
 
这段代码一般被放在 init() 函数中执行。这儿还有一段示例来演示如何根据操作系统来决定输入结束的提示:
 var prompt = "Enter a digit, e.g. 3 "+ "or %s to quit."
 
 func init() {
 	if runtime.GOOS == "windows" {
 		prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")		
 	} else { //Unix-like
 		prompt = fmt.Sprintf(prompt, "Ctrl+D")
 	}
 }

 函数 Abs() 用于返回一个整型数字的绝对值:
 func Abs(x int) int {
 	if x < 0 {
 		return -x
 	}
 	return x	
 }
 
isGreater 用于比较两个整型数字的大小:
 func isGreater(x, y int) bool {
 	if x > y {
 		return true	
 	}
 	return false
 }

if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号):
if val := 10; val > max {
	// do something
}


5.2
Go 语言的函数经常使用两个返回值来表示执行是否成功:返回某个值以及 true 表示成功;返回零值(或 nil)和 false 表示失败,当不使用 true 或 false 
的时候,也可以使用一个 error 类型的变量来代替作为第二个返回值:成功执行的话,error 的值为 nil,否则就会包含相应的错误信息

程序应该在最接近的位置检查所有相关的错误,至少需要暗示用户有错误发生并对函数进行返回,甚至中断程序。

习惯用法
value, err := pack1.Function1(param1)
if err != nil {
	fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1)
	return err
}
// 未发生错误,继续执行:

if err := file.Chmod(0664); err != nil {
	fmt.Println(err)
	return err
}

if value, ok := readData(); ok {
…
}


5.3 

switch用法:前花括号 { 必须和 switch 关键字在同一行。
switch var1 {
	case val1:
		...
	case val2:
		...
	default:
		...
}

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

一旦成功地匹配到某个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您不需要特别使用 break 语句来表示结束。

因此,程序也不会自动地去执行下一个分支的代码。如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 fallthrough 关键字来达到目的。

switch i {
	case 0: // 空分支,只有当 i == 0 时才会进入分支
	case 1:
		f() // 当 i == 0 时函数不会被调用
}

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

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

switch a, b := x[i], y[j]; {
	case a < b: t = -1
	case a == b: t = 0
	case a > b: t = 1
}


5.4

基本形式为:
for 初始化语句; 条件语句; 修饰语句 {}
这三部分组成的循环的头部,它们之间使用分号 ; 相隔,但并不需要括号 () 将它们括起来。例如:for (i = 0; i < 10; i++) { },这是无效的代码!
同样的,左花括号 { 必须和 for 语句在同一行,计数器的生命周期在遇到右花括号 } 时便终止。一般习惯使用 i、j、z 或 ix 等较短的名称命名计数器。

可以在循环中同时使用多个计数器:
for i, j := 0, N; i < j; i, j = i+1, j-1 {}

在使用for循环来遍历字符串的时候,ASCII 编码的字符占用 1 个字节,既每个索引都指向不同的字符,而非 ASCII 编码的字符(占有 2 到 4 个字节)不能
单纯地使用索引来判断是否为同一个字符。

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

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

break 只是退出当前的循环体,而 return 语句提前对函数进行返回,不会执行后续的代码。exit是退出整个程序,后面的程序不再执行,退出。

for-range 可以迭代任何一个集合(包括数组和 map),一般形式为:for ix, val := range coll { }。

val 始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值
(译者注:如果 val 为指针,则会产生指针的拷贝,依旧可以修改集合中的原值)。
一个字符串是 Unicode 编码的字符(或称之为 rune)集合,因此您也可以用它迭代字符串:
每个 rune 字符和索引在 for-range 循环中是一一对应的。它能够自动根据 UTF-8 规则识别 Unicode 编码的字符。

可以使用%c来取出字符串中某个字符:fmt.Printf("pos %d char is %c \n", pos, char)

5.5

一个 break 的作用范围为该语句出现后的最内层的一次循环,它可以被用于任何形式的 for 循环(计数器、条件判断等)。
关键字 continue 忽略剩余的循环体而直接进入下一次循环的过程,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件。

for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:)结尾的单词,使用label可以调到指定的循环

未经允许不得转载:江哥架构师笔记 » 第5章总结:控制结构

分享到:更多 ()

评论 抢沙发

评论前必须登录!